diff options
Diffstat (limited to 'drivers/tty')
| -rw-r--r-- | drivers/tty/pty.c | 64 | ||||
| -rw-r--r-- | drivers/tty/serial/8250/8250_core.c | 23 | ||||
| -rw-r--r-- | drivers/tty/serial/amba-pl011.c | 37 | ||||
| -rw-r--r-- | drivers/tty/tty_io.c | 3 |
4 files changed, 66 insertions, 61 deletions
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 284749fb0f6b..a6d5164c33a9 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
| @@ -69,13 +69,8 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
| 69 | #ifdef CONFIG_UNIX98_PTYS | 69 | #ifdef CONFIG_UNIX98_PTYS |
| 70 | if (tty->driver == ptm_driver) { | 70 | if (tty->driver == ptm_driver) { |
| 71 | mutex_lock(&devpts_mutex); | 71 | mutex_lock(&devpts_mutex); |
| 72 | if (tty->link->driver_data) { | 72 | if (tty->link->driver_data) |
| 73 | struct path *path = tty->link->driver_data; | 73 | devpts_pty_kill(tty->link->driver_data); |
| 74 | |||
| 75 | devpts_pty_kill(path->dentry); | ||
| 76 | path_put(path); | ||
| 77 | kfree(path); | ||
| 78 | } | ||
| 79 | mutex_unlock(&devpts_mutex); | 74 | mutex_unlock(&devpts_mutex); |
| 80 | } | 75 | } |
| 81 | #endif | 76 | #endif |
| @@ -607,25 +602,24 @@ static inline void legacy_pty_init(void) { } | |||
| 607 | static struct cdev ptmx_cdev; | 602 | static struct cdev ptmx_cdev; |
| 608 | 603 | ||
| 609 | /** | 604 | /** |
| 610 | * pty_open_peer - open the peer of a pty | 605 | * ptm_open_peer - open the peer of a pty |
| 611 | * @tty: the peer of the pty being opened | 606 | * @master: the open struct file of the ptmx device node |
| 607 | * @tty: the master of the pty being opened | ||
| 608 | * @flags: the flags for open | ||
| 612 | * | 609 | * |
| 613 | * Open the cached dentry in tty->link, providing a safe way for userspace | 610 | * Provide a race free way for userspace to open the slave end of a pty |
| 614 | * to get the slave end of a pty (where they have the master fd and cannot | 611 | * (where they have the master fd and cannot access or trust the mount |
| 615 | * access or trust the mount namespace /dev/pts was mounted inside). | 612 | * namespace /dev/pts was mounted inside). |
| 616 | */ | 613 | */ |
| 617 | static struct file *pty_open_peer(struct tty_struct *tty, int flags) | 614 | int ptm_open_peer(struct file *master, struct tty_struct *tty, int flags) |
| 618 | { | ||
| 619 | if (tty->driver->subtype != PTY_TYPE_MASTER) | ||
| 620 | return ERR_PTR(-EIO); | ||
| 621 | return dentry_open(tty->link->driver_data, flags, current_cred()); | ||
| 622 | } | ||
| 623 | |||
| 624 | static int pty_get_peer(struct tty_struct *tty, int flags) | ||
| 625 | { | 615 | { |
| 626 | int fd = -1; | 616 | int fd = -1; |
| 627 | struct file *filp = NULL; | 617 | struct file *filp; |
| 628 | int retval = -EINVAL; | 618 | int retval = -EINVAL; |
| 619 | struct path path; | ||
| 620 | |||
| 621 | if (tty->driver != ptm_driver) | ||
| 622 | return -EIO; | ||
| 629 | 623 | ||
| 630 | fd = get_unused_fd_flags(0); | 624 | fd = get_unused_fd_flags(0); |
| 631 | if (fd < 0) { | 625 | if (fd < 0) { |
| @@ -633,7 +627,16 @@ static int pty_get_peer(struct tty_struct *tty, int flags) | |||
| 633 | goto err; | 627 | goto err; |
| 634 | } | 628 | } |
| 635 | 629 | ||
| 636 | filp = pty_open_peer(tty, flags); | 630 | /* Compute the slave's path */ |
| 631 | path.mnt = devpts_mntget(master, tty->driver_data); | ||
| 632 | if (IS_ERR(path.mnt)) { | ||
| 633 | retval = PTR_ERR(path.mnt); | ||
| 634 | goto err_put; | ||
| 635 | } | ||
| 636 | path.dentry = tty->link->driver_data; | ||
| 637 | |||
| 638 | filp = dentry_open(&path, flags, current_cred()); | ||
| 639 | mntput(path.mnt); | ||
| 637 | if (IS_ERR(filp)) { | 640 | if (IS_ERR(filp)) { |
| 638 | retval = PTR_ERR(filp); | 641 | retval = PTR_ERR(filp); |
| 639 | goto err_put; | 642 | goto err_put; |
| @@ -662,8 +665,6 @@ static int pty_unix98_ioctl(struct tty_struct *tty, | |||
| 662 | return pty_get_pktmode(tty, (int __user *)arg); | 665 | return pty_get_pktmode(tty, (int __user *)arg); |
| 663 | case TIOCGPTN: /* Get PT Number */ | 666 | case TIOCGPTN: /* Get PT Number */ |
| 664 | return put_user(tty->index, (unsigned int __user *)arg); | 667 | return put_user(tty->index, (unsigned int __user *)arg); |
| 665 | case TIOCGPTPEER: /* Open the other end */ | ||
| 666 | return pty_get_peer(tty, (int) arg); | ||
| 667 | case TIOCSIG: /* Send signal to other side of pty */ | 668 | case TIOCSIG: /* Send signal to other side of pty */ |
| 668 | return pty_signal(tty, (int) arg); | 669 | return pty_signal(tty, (int) arg); |
| 669 | } | 670 | } |
| @@ -791,7 +792,6 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
| 791 | { | 792 | { |
| 792 | struct pts_fs_info *fsi; | 793 | struct pts_fs_info *fsi; |
| 793 | struct tty_struct *tty; | 794 | struct tty_struct *tty; |
| 794 | struct path *pts_path; | ||
| 795 | struct dentry *dentry; | 795 | struct dentry *dentry; |
| 796 | int retval; | 796 | int retval; |
| 797 | int index; | 797 | int index; |
| @@ -845,26 +845,16 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
| 845 | retval = PTR_ERR(dentry); | 845 | retval = PTR_ERR(dentry); |
| 846 | goto err_release; | 846 | goto err_release; |
| 847 | } | 847 | } |
| 848 | /* We need to cache a fake path for TIOCGPTPEER. */ | 848 | tty->link->driver_data = dentry; |
| 849 | pts_path = kmalloc(sizeof(struct path), GFP_KERNEL); | ||
| 850 | if (!pts_path) | ||
| 851 | goto err_release; | ||
| 852 | pts_path->mnt = filp->f_path.mnt; | ||
| 853 | pts_path->dentry = dentry; | ||
| 854 | path_get(pts_path); | ||
| 855 | tty->link->driver_data = pts_path; | ||
| 856 | 849 | ||
| 857 | retval = ptm_driver->ops->open(tty, filp); | 850 | retval = ptm_driver->ops->open(tty, filp); |
| 858 | if (retval) | 851 | if (retval) |
| 859 | goto err_path_put; | 852 | goto err_release; |
| 860 | 853 | ||
| 861 | tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); | 854 | tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); |
| 862 | 855 | ||
| 863 | tty_unlock(tty); | 856 | tty_unlock(tty); |
| 864 | return 0; | 857 | return 0; |
| 865 | err_path_put: | ||
| 866 | path_put(pts_path); | ||
| 867 | kfree(pts_path); | ||
| 868 | err_release: | 858 | err_release: |
| 869 | tty_unlock(tty); | 859 | tty_unlock(tty); |
| 870 | // This will also put-ref the fsi | 860 | // This will also put-ref the fsi |
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index b5def356af63..1aab3010fbfa 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c | |||
| @@ -1043,13 +1043,24 @@ int serial8250_register_8250_port(struct uart_8250_port *up) | |||
| 1043 | if (up->dl_write) | 1043 | if (up->dl_write) |
| 1044 | uart->dl_write = up->dl_write; | 1044 | uart->dl_write = up->dl_write; |
| 1045 | 1045 | ||
| 1046 | if (serial8250_isa_config != NULL) | 1046 | if (uart->port.type != PORT_8250_CIR) { |
| 1047 | serial8250_isa_config(0, &uart->port, | 1047 | if (serial8250_isa_config != NULL) |
| 1048 | &uart->capabilities); | 1048 | serial8250_isa_config(0, &uart->port, |
| 1049 | &uart->capabilities); | ||
| 1050 | |||
| 1051 | ret = uart_add_one_port(&serial8250_reg, | ||
| 1052 | &uart->port); | ||
| 1053 | if (ret == 0) | ||
| 1054 | ret = uart->port.line; | ||
| 1055 | } else { | ||
| 1056 | dev_info(uart->port.dev, | ||
| 1057 | "skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n", | ||
| 1058 | uart->port.iobase, | ||
| 1059 | (unsigned long long)uart->port.mapbase, | ||
| 1060 | uart->port.irq); | ||
| 1049 | 1061 | ||
| 1050 | ret = uart_add_one_port(&serial8250_reg, &uart->port); | 1062 | ret = 0; |
| 1051 | if (ret == 0) | 1063 | } |
| 1052 | ret = uart->port.line; | ||
| 1053 | } | 1064 | } |
| 1054 | mutex_unlock(&serial_mutex); | 1065 | mutex_unlock(&serial_mutex); |
| 1055 | 1066 | ||
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 8a857bb34fbb..1888d168a41c 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c | |||
| @@ -142,15 +142,7 @@ static struct vendor_data vendor_sbsa = { | |||
| 142 | .fixed_options = true, | 142 | .fixed_options = true, |
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | /* | 145 | #ifdef CONFIG_ACPI_SPCR_TABLE |
| 146 | * Erratum 44 for QDF2432v1 and QDF2400v1 SoCs describes the BUSY bit as | ||
| 147 | * occasionally getting stuck as 1. To avoid the potential for a hang, check | ||
| 148 | * TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART | ||
| 149 | * implementations, so only do so if an affected platform is detected in | ||
| 150 | * parse_spcr(). | ||
| 151 | */ | ||
| 152 | static bool qdf2400_e44_present = false; | ||
| 153 | |||
| 154 | static struct vendor_data vendor_qdt_qdf2400_e44 = { | 146 | static struct vendor_data vendor_qdt_qdf2400_e44 = { |
| 155 | .reg_offset = pl011_std_offsets, | 147 | .reg_offset = pl011_std_offsets, |
| 156 | .fr_busy = UART011_FR_TXFE, | 148 | .fr_busy = UART011_FR_TXFE, |
| @@ -165,6 +157,7 @@ static struct vendor_data vendor_qdt_qdf2400_e44 = { | |||
| 165 | .always_enabled = true, | 157 | .always_enabled = true, |
| 166 | .fixed_options = true, | 158 | .fixed_options = true, |
| 167 | }; | 159 | }; |
| 160 | #endif | ||
| 168 | 161 | ||
| 169 | static u16 pl011_st_offsets[REG_ARRAY_SIZE] = { | 162 | static u16 pl011_st_offsets[REG_ARRAY_SIZE] = { |
| 170 | [REG_DR] = UART01x_DR, | 163 | [REG_DR] = UART01x_DR, |
| @@ -2375,12 +2368,14 @@ static int __init pl011_console_match(struct console *co, char *name, int idx, | |||
| 2375 | resource_size_t addr; | 2368 | resource_size_t addr; |
| 2376 | int i; | 2369 | int i; |
| 2377 | 2370 | ||
| 2378 | if (strcmp(name, "qdf2400_e44") == 0) { | 2371 | /* |
| 2379 | pr_info_once("UART: Working around QDF2400 SoC erratum 44"); | 2372 | * Systems affected by the Qualcomm Technologies QDF2400 E44 erratum |
| 2380 | qdf2400_e44_present = true; | 2373 | * have a distinct console name, so make sure we check for that. |
| 2381 | } else if (strcmp(name, "pl011") != 0) { | 2374 | * The actual implementation of the erratum occurs in the probe |
| 2375 | * function. | ||
| 2376 | */ | ||
| 2377 | if ((strcmp(name, "qdf2400_e44") != 0) && (strcmp(name, "pl011") != 0)) | ||
| 2382 | return -ENODEV; | 2378 | return -ENODEV; |
| 2383 | } | ||
| 2384 | 2379 | ||
| 2385 | if (uart_parse_earlycon(options, &iotype, &addr, &options)) | 2380 | if (uart_parse_earlycon(options, &iotype, &addr, &options)) |
| 2386 | return -ENODEV; | 2381 | return -ENODEV; |
| @@ -2734,11 +2729,17 @@ static int sbsa_uart_probe(struct platform_device *pdev) | |||
| 2734 | } | 2729 | } |
| 2735 | uap->port.irq = ret; | 2730 | uap->port.irq = ret; |
| 2736 | 2731 | ||
| 2737 | uap->reg_offset = vendor_sbsa.reg_offset; | 2732 | #ifdef CONFIG_ACPI_SPCR_TABLE |
| 2738 | uap->vendor = qdf2400_e44_present ? | 2733 | if (qdf2400_e44_present) { |
| 2739 | &vendor_qdt_qdf2400_e44 : &vendor_sbsa; | 2734 | dev_info(&pdev->dev, "working around QDF2400 SoC erratum 44\n"); |
| 2735 | uap->vendor = &vendor_qdt_qdf2400_e44; | ||
| 2736 | } else | ||
| 2737 | #endif | ||
| 2738 | uap->vendor = &vendor_sbsa; | ||
| 2739 | |||
| 2740 | uap->reg_offset = uap->vendor->reg_offset; | ||
| 2740 | uap->fifosize = 32; | 2741 | uap->fifosize = 32; |
| 2741 | uap->port.iotype = vendor_sbsa.access_32b ? UPIO_MEM32 : UPIO_MEM; | 2742 | uap->port.iotype = uap->vendor->access_32b ? UPIO_MEM32 : UPIO_MEM; |
| 2742 | uap->port.ops = &sbsa_uart_pops; | 2743 | uap->port.ops = &sbsa_uart_pops; |
| 2743 | uap->fixed_baud = baudrate; | 2744 | uap->fixed_baud = baudrate; |
| 2744 | 2745 | ||
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 974b13d24401..10c4038c0e8d 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
| @@ -2518,6 +2518,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 2518 | case TIOCSSERIAL: | 2518 | case TIOCSSERIAL: |
| 2519 | tty_warn_deprecated_flags(p); | 2519 | tty_warn_deprecated_flags(p); |
| 2520 | break; | 2520 | break; |
| 2521 | case TIOCGPTPEER: | ||
| 2522 | /* Special because the struct file is needed */ | ||
| 2523 | return ptm_open_peer(file, tty, (int)arg); | ||
| 2521 | default: | 2524 | default: |
| 2522 | retval = tty_jobctrl_ioctl(tty, real_tty, file, cmd, arg); | 2525 | retval = tty_jobctrl_ioctl(tty, real_tty, file, cmd, arg); |
| 2523 | if (retval != -ENOIOCTLCMD) | 2526 | if (retval != -ENOIOCTLCMD) |
