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 | static bool is_enabled(struct uart_port *port, int bit) | 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 | return true; | 56 | return true; |
| 57 | return false; | 57 | return false; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | static void enable(struct uart_port *port, int bit) | 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 | static void disable(struct uart_port *port, int bit) | 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 | #define is_tx_enabled(port) is_enabled(port, tx_enabled_bit) | 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 | /* Forward declare this for the dma callbacks*/ | 314 | /* Forward declare this for the dma callbacks*/ |
| 315 | static void lpuart_dma_tx_complete(void *arg); | 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 | static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport) | 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 | UARTFIFO_FIFOSIZE_MASK); | 1702 | UARTFIFO_FIFOSIZE_MASK); |
| 1702 | 1703 | ||
| 1703 | /* | 1704 | /* |
| 1704 | * The LS1028A has a fixed length of 16 words. Although it supports the | 1705 | * The LS1021A and LS1028A have a fixed FIFO depth of 16 words. |
| 1705 | * RX/TXSIZE fields their encoding is different. Eg the reference manual | 1706 | * Although they support the RX/TXSIZE fields, their encoding is |
| 1706 | * states 0b101 is 16 words. | 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 | sport->rxfifo_size = 16; | 1710 | sport->rxfifo_size = 16; |
| 1710 | sport->txfifo_size = 16; | 1711 | sport->txfifo_size = 16; |
| 1711 | sport->port.fifosize = sport->txfifo_size; | 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 | return; | 743 | return; |
| 744 | 744 | ||
| 745 | if ((unsigned)value < ARRAY_SIZE(func_table)) { | 745 | if ((unsigned)value < ARRAY_SIZE(func_table)) { |
| 746 | unsigned long flags; | ||
| 747 | |||
| 748 | spin_lock_irqsave(&func_buf_lock, flags); | ||
| 746 | if (func_table[value]) | 749 | if (func_table[value]) |
| 747 | puts_queue(vc, func_table[value]); | 750 | puts_queue(vc, func_table[value]); |
| 751 | spin_unlock_irqrestore(&func_buf_lock, flags); | ||
| 752 | |||
| 748 | } else | 753 | } else |
| 749 | pr_err("k_fn called with value=%d\n", value); | 754 | pr_err("k_fn called with value=%d\n", value); |
| 750 | } | 755 | } |
| @@ -1991,13 +1996,11 @@ out: · 1240 unmodified lines | |||
| 1991 | #undef s | 1996 | #undef s |
| 1992 | #undef v | 1997 | #undef v |
| 1993 | 1998 | ||
| 1994 | /* FIXME: This one needs untangling and locking */ | 1999 | /* FIXME: This one needs untangling */ |
| 1995 | int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) | 2000 | int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) |
| 1996 | { | 2001 | { |
| 1997 | struct kbsentry *kbs; | 2002 | struct kbsentry *kbs; |
| 1998 | char *p; | ||
| 1999 | u_char *q; | 2003 | u_char *q; |
| 2000 | u_char __user *up; | ||
| 2001 | int sz, fnw_sz; | 2004 | int sz, fnw_sz; |
| 2002 | int delta; | 2005 | int delta; |
| 2003 | char *first_free, *fj, *fnw; | 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 | i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC); | 2026 | i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC); |
| 2024 | 2027 | ||
| 2025 | switch (cmd) { | 2028 | switch (cmd) { |
| 2026 | case KDGKBSENT: | 2029 | case KDGKBSENT: { |
| 2027 | sz = sizeof(kbs->kb_string) - 1; /* sz should have been | 2030 | /* size should have been a struct member */ |
| 2028 | a struct member */ | 2031 | ssize_t len = sizeof(user_kdgkb->kb_string); |
| 2029 | up = user_kdgkb->kb_string; | 2032 | |
| 2030 | p = func_table[i]; | 2033 | spin_lock_irqsave(&func_buf_lock, flags); |
| 2031 | if(p) | 2034 | len = strlcpy(kbs->kb_string, func_table[i] ? : "", len); |
| 2032 | for ( ; *p && sz; p++, sz--) | 2035 | spin_unlock_irqrestore(&func_buf_lock, flags); |
| 2033 | if (put_user(*p, up++)) { | 2036 | |
| 2034 | ret = -EFAULT; | 2037 | ret = copy_to_user(user_kdgkb->kb_string, kbs->kb_string, |
| 2035 | goto reterr; | 2038 | len + 1) ? -EFAULT : 0; |
| 2036 | } | 2039 | |
| 2037 | if (put_user('\0', up)) { | 2040 | goto reterr; |
| 2038 | ret = -EFAULT; | 2041 | } |
| 2039 | goto reterr; | ||
| 2040 | } | ||
| 2041 | kfree(kbs); | ||
| 2042 | return ((p && *p) ? -EOVERFLOW : 0); | ||
| 2043 | case KDSKBSENT: | 2042 | case KDSKBSENT: |
| 2044 | if (!perm) { | 2043 | if (!perm) { |
| 2045 | ret = -EPERM; | 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 | static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, | 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 | struct unimapdesc tmp; | 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 | return -EFAULT; | 557 | return -EFAULT; |
| 558 | switch (cmd) { | 558 | switch (cmd) { |
| 559 | case PIO_UNIMAP: | 559 | case PIO_UNIMAP: |
| 560 | if (!perm) | ||
| 561 | return -EPERM; | ||
| 560 | return con_set_unimap(vc, tmp.entry_ct, tmp.entries); | 562 | return con_set_unimap(vc, tmp.entry_ct, tmp.entries); |
| 561 | case GIO_UNIMAP: | 563 | case GIO_UNIMAP: |
| 562 | if (fg_console != vc->vc_num) | 564 | if (!perm && fg_console != vc->vc_num) |
| 563 | return -EPERM; | 565 | return -EPERM; |
| 564 | return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), | 566 | return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), |
| 565 | tmp.entries); | 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 | case PIO_UNIMAP: | 642 | case PIO_UNIMAP: |
| 641 | case GIO_UNIMAP: | 643 | case GIO_UNIMAP: |
| 642 | if (!perm) | 644 | return do_unimap_ioctl(cmd, up, perm, vc); |
| 643 | return -EPERM; | ||
| 644 | |||
| 645 | return do_unimap_ioctl(cmd, up, vc); | ||
| 646 | 645 | ||
| 647 | default: | 646 | default: |
| 648 | return -ENOIOCTLCMD; | 647 | return -ENOIOCTLCMD; |