diff options
Diffstat (limited to 'drivers/tty')
| -rw-r--r-- | drivers/tty/ehv_bytechan.c | 17 | ||||
| -rw-r--r-- | drivers/tty/serdev/core.c | 12 | ||||
| -rw-r--r-- | drivers/tty/serdev/serdev-ttyport.c | 21 | ||||
| -rw-r--r-- | drivers/tty/serial/8250/8250_port.c | 21 | ||||
| -rw-r--r-- | drivers/tty/serial/altera_jtaguart.c | 1 | ||||
| -rw-r--r-- | drivers/tty/serial/altera_uart.c | 1 | ||||
| -rw-r--r-- | drivers/tty/serial/efm32-uart.c | 11 | ||||
| -rw-r--r-- | drivers/tty/serial/ifx6x60.c | 2 | ||||
| -rw-r--r-- | drivers/tty/serial/imx.c | 14 | ||||
| -rw-r--r-- | drivers/tty/serial/serial_core.c | 6 | ||||
| -rw-r--r-- | drivers/tty/tty_port.c | 75 |
11 files changed, 141 insertions, 40 deletions
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 7ac9bcdf1e61..61fe8d6fd24e 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c | |||
| @@ -764,7 +764,7 @@ static int __init ehv_bc_init(void) | |||
| 764 | ehv_bc_driver = alloc_tty_driver(count); | 764 | ehv_bc_driver = alloc_tty_driver(count); |
| 765 | if (!ehv_bc_driver) { | 765 | if (!ehv_bc_driver) { |
| 766 | ret = -ENOMEM; | 766 | ret = -ENOMEM; |
| 767 | goto error; | 767 | goto err_free_bcs; |
| 768 | } | 768 | } |
| 769 | 769 | ||
| 770 | ehv_bc_driver->driver_name = "ehv-bc"; | 770 | ehv_bc_driver->driver_name = "ehv-bc"; |
| @@ -778,24 +778,23 @@ static int __init ehv_bc_init(void) | |||
| 778 | ret = tty_register_driver(ehv_bc_driver); | 778 | ret = tty_register_driver(ehv_bc_driver); |
| 779 | if (ret) { | 779 | if (ret) { |
| 780 | pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret); | 780 | pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret); |
| 781 | goto error; | 781 | goto err_put_tty_driver; |
| 782 | } | 782 | } |
| 783 | 783 | ||
| 784 | ret = platform_driver_register(&ehv_bc_tty_driver); | 784 | ret = platform_driver_register(&ehv_bc_tty_driver); |
| 785 | if (ret) { | 785 | if (ret) { |
| 786 | pr_err("ehv-bc: could not register platform driver (ret=%i)\n", | 786 | pr_err("ehv-bc: could not register platform driver (ret=%i)\n", |
| 787 | ret); | 787 | ret); |
| 788 | goto error; | 788 | goto err_deregister_tty_driver; |
| 789 | } | 789 | } |
| 790 | 790 | ||
| 791 | return 0; | 791 | return 0; |
| 792 | 792 | ||
| 793 | error: | 793 | err_deregister_tty_driver: |
| 794 | if (ehv_bc_driver) { | 794 | tty_unregister_driver(ehv_bc_driver); |
| 795 | tty_unregister_driver(ehv_bc_driver); | 795 | err_put_tty_driver: |
| 796 | put_tty_driver(ehv_bc_driver); | 796 | put_tty_driver(ehv_bc_driver); |
| 797 | } | 797 | err_free_bcs: |
| 798 | |||
| 799 | kfree(bcs); | 798 | kfree(bcs); |
| 800 | 799 | ||
| 801 | return ret; | 800 | return ret; |
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 433de5ea9b02..f71b47334149 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c | |||
| @@ -122,6 +122,18 @@ void serdev_device_write_wakeup(struct serdev_device *serdev) | |||
| 122 | } | 122 | } |
| 123 | EXPORT_SYMBOL_GPL(serdev_device_write_wakeup); | 123 | EXPORT_SYMBOL_GPL(serdev_device_write_wakeup); |
| 124 | 124 | ||
| 125 | int serdev_device_write_buf(struct serdev_device *serdev, | ||
| 126 | const unsigned char *buf, size_t count) | ||
| 127 | { | ||
| 128 | struct serdev_controller *ctrl = serdev->ctrl; | ||
| 129 | |||
| 130 | if (!ctrl || !ctrl->ops->write_buf) | ||
| 131 | return -EINVAL; | ||
| 132 | |||
| 133 | return ctrl->ops->write_buf(ctrl, buf, count); | ||
| 134 | } | ||
| 135 | EXPORT_SYMBOL_GPL(serdev_device_write_buf); | ||
| 136 | |||
| 125 | int serdev_device_write(struct serdev_device *serdev, | 137 | int serdev_device_write(struct serdev_device *serdev, |
| 126 | const unsigned char *buf, size_t count, | 138 | const unsigned char *buf, size_t count, |
| 127 | unsigned long timeout) | 139 | unsigned long timeout) |
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c index 487c88f6aa0e..d0a021c93986 100644 --- a/drivers/tty/serdev/serdev-ttyport.c +++ b/drivers/tty/serdev/serdev-ttyport.c | |||
| @@ -102,9 +102,6 @@ static int ttyport_open(struct serdev_controller *ctrl) | |||
| 102 | return PTR_ERR(tty); | 102 | return PTR_ERR(tty); |
| 103 | serport->tty = tty; | 103 | serport->tty = tty; |
| 104 | 104 | ||
| 105 | serport->port->client_ops = &client_ops; | ||
| 106 | serport->port->client_data = ctrl; | ||
| 107 | |||
| 108 | if (tty->ops->open) | 105 | if (tty->ops->open) |
| 109 | tty->ops->open(serport->tty, NULL); | 106 | tty->ops->open(serport->tty, NULL); |
| 110 | else | 107 | else |
| @@ -215,6 +212,7 @@ struct device *serdev_tty_port_register(struct tty_port *port, | |||
| 215 | struct device *parent, | 212 | struct device *parent, |
| 216 | struct tty_driver *drv, int idx) | 213 | struct tty_driver *drv, int idx) |
| 217 | { | 214 | { |
| 215 | const struct tty_port_client_operations *old_ops; | ||
| 218 | struct serdev_controller *ctrl; | 216 | struct serdev_controller *ctrl; |
| 219 | struct serport *serport; | 217 | struct serport *serport; |
| 220 | int ret; | 218 | int ret; |
| @@ -233,28 +231,37 @@ struct device *serdev_tty_port_register(struct tty_port *port, | |||
| 233 | 231 | ||
| 234 | ctrl->ops = &ctrl_ops; | 232 | ctrl->ops = &ctrl_ops; |
| 235 | 233 | ||
| 234 | old_ops = port->client_ops; | ||
| 235 | port->client_ops = &client_ops; | ||
| 236 | port->client_data = ctrl; | ||
| 237 | |||
| 236 | ret = serdev_controller_add(ctrl); | 238 | ret = serdev_controller_add(ctrl); |
| 237 | if (ret) | 239 | if (ret) |
| 238 | goto err_controller_put; | 240 | goto err_reset_data; |
| 239 | 241 | ||
| 240 | dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx); | 242 | dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx); |
| 241 | return &ctrl->dev; | 243 | return &ctrl->dev; |
| 242 | 244 | ||
| 243 | err_controller_put: | 245 | err_reset_data: |
| 246 | port->client_data = NULL; | ||
| 247 | port->client_ops = old_ops; | ||
| 244 | serdev_controller_put(ctrl); | 248 | serdev_controller_put(ctrl); |
| 249 | |||
| 245 | return ERR_PTR(ret); | 250 | return ERR_PTR(ret); |
| 246 | } | 251 | } |
| 247 | 252 | ||
| 248 | void serdev_tty_port_unregister(struct tty_port *port) | 253 | int serdev_tty_port_unregister(struct tty_port *port) |
| 249 | { | 254 | { |
| 250 | struct serdev_controller *ctrl = port->client_data; | 255 | struct serdev_controller *ctrl = port->client_data; |
| 251 | struct serport *serport = serdev_controller_get_drvdata(ctrl); | 256 | struct serport *serport = serdev_controller_get_drvdata(ctrl); |
| 252 | 257 | ||
| 253 | if (!serport) | 258 | if (!serport) |
| 254 | return; | 259 | return -ENODEV; |
| 255 | 260 | ||
| 256 | serdev_controller_remove(ctrl); | 261 | serdev_controller_remove(ctrl); |
| 257 | port->client_ops = NULL; | 262 | port->client_ops = NULL; |
| 258 | port->client_data = NULL; | 263 | port->client_data = NULL; |
| 259 | serdev_controller_put(ctrl); | 264 | serdev_controller_put(ctrl); |
| 265 | |||
| 266 | return 0; | ||
| 260 | } | 267 | } |
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 09a65a3ec7f7..68fd045a7025 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | /* | 47 | /* |
| 48 | * These are definitions for the Exar XR17V35X and XR17(C|D)15X | 48 | * These are definitions for the Exar XR17V35X and XR17(C|D)15X |
| 49 | */ | 49 | */ |
| 50 | #define UART_EXAR_INT0 0x80 | ||
| 50 | #define UART_EXAR_SLEEP 0x8b /* Sleep mode */ | 51 | #define UART_EXAR_SLEEP 0x8b /* Sleep mode */ |
| 51 | #define UART_EXAR_DVID 0x8d /* Device identification */ | 52 | #define UART_EXAR_DVID 0x8d /* Device identification */ |
| 52 | 53 | ||
| @@ -1337,7 +1338,7 @@ out_lock: | |||
| 1337 | /* | 1338 | /* |
| 1338 | * Check if the device is a Fintek F81216A | 1339 | * Check if the device is a Fintek F81216A |
| 1339 | */ | 1340 | */ |
| 1340 | if (port->type == PORT_16550A) | 1341 | if (port->type == PORT_16550A && port->iotype == UPIO_PORT) |
| 1341 | fintek_8250_probe(up); | 1342 | fintek_8250_probe(up); |
| 1342 | 1343 | ||
| 1343 | if (up->capabilities != old_capabilities) { | 1344 | if (up->capabilities != old_capabilities) { |
| @@ -1869,17 +1870,13 @@ static int serial8250_default_handle_irq(struct uart_port *port) | |||
| 1869 | static int exar_handle_irq(struct uart_port *port) | 1870 | static int exar_handle_irq(struct uart_port *port) |
| 1870 | { | 1871 | { |
| 1871 | unsigned int iir = serial_port_in(port, UART_IIR); | 1872 | unsigned int iir = serial_port_in(port, UART_IIR); |
| 1872 | int ret; | 1873 | int ret = 0; |
| 1873 | 1874 | ||
| 1874 | ret = serial8250_handle_irq(port, iir); | 1875 | if (((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) && |
| 1876 | serial_port_in(port, UART_EXAR_INT0) != 0) | ||
| 1877 | ret = 1; | ||
| 1875 | 1878 | ||
| 1876 | if ((port->type == PORT_XR17V35X) || | 1879 | ret |= serial8250_handle_irq(port, iir); |
| 1877 | (port->type == PORT_XR17D15X)) { | ||
| 1878 | serial_port_in(port, 0x80); | ||
| 1879 | serial_port_in(port, 0x81); | ||
| 1880 | serial_port_in(port, 0x82); | ||
| 1881 | serial_port_in(port, 0x83); | ||
| 1882 | } | ||
| 1883 | 1880 | ||
| 1884 | return ret; | 1881 | return ret; |
| 1885 | } | 1882 | } |
| @@ -2177,6 +2174,8 @@ int serial8250_do_startup(struct uart_port *port) | |||
| 2177 | serial_port_in(port, UART_RX); | 2174 | serial_port_in(port, UART_RX); |
| 2178 | serial_port_in(port, UART_IIR); | 2175 | serial_port_in(port, UART_IIR); |
| 2179 | serial_port_in(port, UART_MSR); | 2176 | serial_port_in(port, UART_MSR); |
| 2177 | if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) | ||
| 2178 | serial_port_in(port, UART_EXAR_INT0); | ||
| 2180 | 2179 | ||
| 2181 | /* | 2180 | /* |
| 2182 | * At this point, there's no way the LSR could still be 0xff; | 2181 | * At this point, there's no way the LSR could still be 0xff; |
| @@ -2335,6 +2334,8 @@ dont_test_tx_en: | |||
| 2335 | serial_port_in(port, UART_RX); | 2334 | serial_port_in(port, UART_RX); |
| 2336 | serial_port_in(port, UART_IIR); | 2335 | serial_port_in(port, UART_IIR); |
| 2337 | serial_port_in(port, UART_MSR); | 2336 | serial_port_in(port, UART_MSR); |
| 2337 | if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) | ||
| 2338 | serial_port_in(port, UART_EXAR_INT0); | ||
| 2338 | up->lsr_saved_flags = 0; | 2339 | up->lsr_saved_flags = 0; |
| 2339 | up->msr_saved_flags = 0; | 2340 | up->msr_saved_flags = 0; |
| 2340 | 2341 | ||
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index 18e3f8342b85..0475f5d261ce 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c | |||
| @@ -478,6 +478,7 @@ static int altera_jtaguart_remove(struct platform_device *pdev) | |||
| 478 | 478 | ||
| 479 | port = &altera_jtaguart_ports[i].port; | 479 | port = &altera_jtaguart_ports[i].port; |
| 480 | uart_remove_one_port(&altera_jtaguart_driver, port); | 480 | uart_remove_one_port(&altera_jtaguart_driver, port); |
| 481 | iounmap(port->membase); | ||
| 481 | 482 | ||
| 482 | return 0; | 483 | return 0; |
| 483 | } | 484 | } |
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 46d3438a0d27..3e4b717670d7 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c | |||
| @@ -615,6 +615,7 @@ static int altera_uart_remove(struct platform_device *pdev) | |||
| 615 | if (port) { | 615 | if (port) { |
| 616 | uart_remove_one_port(&altera_uart_driver, port); | 616 | uart_remove_one_port(&altera_uart_driver, port); |
| 617 | port->mapbase = 0; | 617 | port->mapbase = 0; |
| 618 | iounmap(port->membase); | ||
| 618 | } | 619 | } |
| 619 | 620 | ||
| 620 | return 0; | 621 | return 0; |
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index ebd8569f9ad5..9fff25be87f9 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #define UARTn_FRAME 0x04 | 27 | #define UARTn_FRAME 0x04 |
| 28 | #define UARTn_FRAME_DATABITS__MASK 0x000f | 28 | #define UARTn_FRAME_DATABITS__MASK 0x000f |
| 29 | #define UARTn_FRAME_DATABITS(n) ((n) - 3) | 29 | #define UARTn_FRAME_DATABITS(n) ((n) - 3) |
| 30 | #define UARTn_FRAME_PARITY__MASK 0x0300 | ||
| 30 | #define UARTn_FRAME_PARITY_NONE 0x0000 | 31 | #define UARTn_FRAME_PARITY_NONE 0x0000 |
| 31 | #define UARTn_FRAME_PARITY_EVEN 0x0200 | 32 | #define UARTn_FRAME_PARITY_EVEN 0x0200 |
| 32 | #define UARTn_FRAME_PARITY_ODD 0x0300 | 33 | #define UARTn_FRAME_PARITY_ODD 0x0300 |
| @@ -572,12 +573,16 @@ static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port, | |||
| 572 | 16 * (4 + (clkdiv >> 6))); | 573 | 16 * (4 + (clkdiv >> 6))); |
| 573 | 574 | ||
| 574 | frame = efm32_uart_read32(efm_port, UARTn_FRAME); | 575 | frame = efm32_uart_read32(efm_port, UARTn_FRAME); |
| 575 | if (frame & UARTn_FRAME_PARITY_ODD) | 576 | switch (frame & UARTn_FRAME_PARITY__MASK) { |
| 577 | case UARTn_FRAME_PARITY_ODD: | ||
| 576 | *parity = 'o'; | 578 | *parity = 'o'; |
| 577 | else if (frame & UARTn_FRAME_PARITY_EVEN) | 579 | break; |
| 580 | case UARTn_FRAME_PARITY_EVEN: | ||
| 578 | *parity = 'e'; | 581 | *parity = 'e'; |
| 579 | else | 582 | break; |
| 583 | default: | ||
| 580 | *parity = 'n'; | 584 | *parity = 'n'; |
| 585 | } | ||
| 581 | 586 | ||
| 582 | *bits = (frame & UARTn_FRAME_DATABITS__MASK) - | 587 | *bits = (frame & UARTn_FRAME_DATABITS__MASK) - |
| 583 | UARTn_FRAME_DATABITS(4) + 4; | 588 | UARTn_FRAME_DATABITS(4) + 4; |
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 157883653256..f190a84a0246 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c | |||
| @@ -1382,9 +1382,9 @@ static struct spi_driver ifx_spi_driver = { | |||
| 1382 | static void __exit ifx_spi_exit(void) | 1382 | static void __exit ifx_spi_exit(void) |
| 1383 | { | 1383 | { |
| 1384 | /* unregister */ | 1384 | /* unregister */ |
| 1385 | spi_unregister_driver(&ifx_spi_driver); | ||
| 1385 | tty_unregister_driver(tty_drv); | 1386 | tty_unregister_driver(tty_drv); |
| 1386 | put_tty_driver(tty_drv); | 1387 | put_tty_driver(tty_drv); |
| 1387 | spi_unregister_driver(&ifx_spi_driver); | ||
| 1388 | unregister_reboot_notifier(&ifx_modem_reboot_notifier_block); | 1388 | unregister_reboot_notifier(&ifx_modem_reboot_notifier_block); |
| 1389 | } | 1389 | } |
| 1390 | 1390 | ||
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 33509b4beaec..bbefddd92bfe 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
| @@ -2184,7 +2184,9 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
| 2184 | * and DCD (when they are outputs) or enables the respective | 2184 | * and DCD (when they are outputs) or enables the respective |
| 2185 | * irqs. So set this bit early, i.e. before requesting irqs. | 2185 | * irqs. So set this bit early, i.e. before requesting irqs. |
| 2186 | */ | 2186 | */ |
| 2187 | writel(UFCR_DCEDTE, sport->port.membase + UFCR); | 2187 | reg = readl(sport->port.membase + UFCR); |
| 2188 | if (!(reg & UFCR_DCEDTE)) | ||
| 2189 | writel(reg | UFCR_DCEDTE, sport->port.membase + UFCR); | ||
| 2188 | 2190 | ||
| 2189 | /* | 2191 | /* |
| 2190 | * Disable UCR3_RI and UCR3_DCD irqs. They are also not | 2192 | * Disable UCR3_RI and UCR3_DCD irqs. They are also not |
| @@ -2195,7 +2197,15 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
| 2195 | sport->port.membase + UCR3); | 2197 | sport->port.membase + UCR3); |
| 2196 | 2198 | ||
| 2197 | } else { | 2199 | } else { |
| 2198 | writel(0, sport->port.membase + UFCR); | 2200 | unsigned long ucr3 = UCR3_DSR; |
| 2201 | |||
| 2202 | reg = readl(sport->port.membase + UFCR); | ||
| 2203 | if (reg & UFCR_DCEDTE) | ||
| 2204 | writel(reg & ~UFCR_DCEDTE, sport->port.membase + UFCR); | ||
| 2205 | |||
| 2206 | if (!is_imx1_uart(sport)) | ||
| 2207 | ucr3 |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP; | ||
| 2208 | writel(ucr3, sport->port.membase + UCR3); | ||
| 2199 | } | 2209 | } |
| 2200 | 2210 | ||
| 2201 | clk_disable_unprepare(sport->clk_ipg); | 2211 | clk_disable_unprepare(sport->clk_ipg); |
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 0f45b7884a2c..13bfd5dcffce 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
| @@ -2083,7 +2083,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) | |||
| 2083 | mutex_lock(&port->mutex); | 2083 | mutex_lock(&port->mutex); |
| 2084 | 2084 | ||
| 2085 | tty_dev = device_find_child(uport->dev, &match, serial_match_port); | 2085 | tty_dev = device_find_child(uport->dev, &match, serial_match_port); |
| 2086 | if (device_may_wakeup(tty_dev)) { | 2086 | if (tty_dev && device_may_wakeup(tty_dev)) { |
| 2087 | if (!enable_irq_wake(uport->irq)) | 2087 | if (!enable_irq_wake(uport->irq)) |
| 2088 | uport->irq_wake = 1; | 2088 | uport->irq_wake = 1; |
| 2089 | put_device(tty_dev); | 2089 | put_device(tty_dev); |
| @@ -2782,7 +2782,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) | |||
| 2782 | * Register the port whether it's detected or not. This allows | 2782 | * Register the port whether it's detected or not. This allows |
| 2783 | * setserial to be used to alter this port's parameters. | 2783 | * setserial to be used to alter this port's parameters. |
| 2784 | */ | 2784 | */ |
| 2785 | tty_dev = tty_port_register_device_attr(port, drv->tty_driver, | 2785 | tty_dev = tty_port_register_device_attr_serdev(port, drv->tty_driver, |
| 2786 | uport->line, uport->dev, port, uport->tty_groups); | 2786 | uport->line, uport->dev, port, uport->tty_groups); |
| 2787 | if (likely(!IS_ERR(tty_dev))) { | 2787 | if (likely(!IS_ERR(tty_dev))) { |
| 2788 | device_set_wakeup_capable(tty_dev, 1); | 2788 | device_set_wakeup_capable(tty_dev, 1); |
| @@ -2845,7 +2845,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) | |||
| 2845 | /* | 2845 | /* |
| 2846 | * Remove the devices from the tty layer | 2846 | * Remove the devices from the tty layer |
| 2847 | */ | 2847 | */ |
| 2848 | tty_unregister_device(drv->tty_driver, uport->line); | 2848 | tty_port_unregister_device(port, drv->tty_driver, uport->line); |
| 2849 | 2849 | ||
| 2850 | tty = tty_port_tty_get(port); | 2850 | tty = tty_port_tty_get(port); |
| 2851 | if (tty) { | 2851 | if (tty) { |
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 1d21a9c1d33e..4fb3165384c4 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c | |||
| @@ -34,7 +34,9 @@ static int tty_port_default_receive_buf(struct tty_port *port, | |||
| 34 | if (!disc) | 34 | if (!disc) |
| 35 | return 0; | 35 | return 0; |
| 36 | 36 | ||
| 37 | mutex_lock(&tty->atomic_write_lock); | ||
| 37 | ret = tty_ldisc_receive_buf(disc, p, (char *)f, count); | 38 | ret = tty_ldisc_receive_buf(disc, p, (char *)f, count); |
| 39 | mutex_unlock(&tty->atomic_write_lock); | ||
| 38 | 40 | ||
| 39 | tty_ldisc_deref(disc); | 41 | tty_ldisc_deref(disc); |
| 40 | 42 | ||
| @@ -129,19 +131,85 @@ struct device *tty_port_register_device_attr(struct tty_port *port, | |||
| 129 | struct device *device, void *drvdata, | 131 | struct device *device, void *drvdata, |
| 130 | const struct attribute_group **attr_grp) | 132 | const struct attribute_group **attr_grp) |
| 131 | { | 133 | { |
| 134 | tty_port_link_device(port, driver, index); | ||
| 135 | return tty_register_device_attr(driver, index, device, drvdata, | ||
| 136 | attr_grp); | ||
| 137 | } | ||
| 138 | EXPORT_SYMBOL_GPL(tty_port_register_device_attr); | ||
| 139 | |||
| 140 | /** | ||
| 141 | * tty_port_register_device_attr_serdev - register tty or serdev device | ||
| 142 | * @port: tty_port of the device | ||
| 143 | * @driver: tty_driver for this device | ||
| 144 | * @index: index of the tty | ||
| 145 | * @device: parent if exists, otherwise NULL | ||
| 146 | * @drvdata: driver data for the device | ||
| 147 | * @attr_grp: attribute group for the device | ||
| 148 | * | ||
| 149 | * Register a serdev or tty device depending on if the parent device has any | ||
| 150 | * defined serdev clients or not. | ||
| 151 | */ | ||
| 152 | struct device *tty_port_register_device_attr_serdev(struct tty_port *port, | ||
| 153 | struct tty_driver *driver, unsigned index, | ||
| 154 | struct device *device, void *drvdata, | ||
| 155 | const struct attribute_group **attr_grp) | ||
| 156 | { | ||
| 132 | struct device *dev; | 157 | struct device *dev; |
| 133 | 158 | ||
| 134 | tty_port_link_device(port, driver, index); | 159 | tty_port_link_device(port, driver, index); |
| 135 | 160 | ||
| 136 | dev = serdev_tty_port_register(port, device, driver, index); | 161 | dev = serdev_tty_port_register(port, device, driver, index); |
| 137 | if (PTR_ERR(dev) != -ENODEV) | 162 | if (PTR_ERR(dev) != -ENODEV) { |
| 138 | /* Skip creating cdev if we registered a serdev device */ | 163 | /* Skip creating cdev if we registered a serdev device */ |
| 139 | return dev; | 164 | return dev; |
| 165 | } | ||
| 140 | 166 | ||
| 141 | return tty_register_device_attr(driver, index, device, drvdata, | 167 | return tty_register_device_attr(driver, index, device, drvdata, |
| 142 | attr_grp); | 168 | attr_grp); |
| 143 | } | 169 | } |
| 144 | EXPORT_SYMBOL_GPL(tty_port_register_device_attr); | 170 | EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev); |
| 171 | |||
| 172 | /** | ||
| 173 | * tty_port_register_device_serdev - register tty or serdev device | ||
| 174 | * @port: tty_port of the device | ||
| 175 | * @driver: tty_driver for this device | ||
| 176 | * @index: index of the tty | ||
| 177 | * @device: parent if exists, otherwise NULL | ||
| 178 | * | ||
| 179 | * Register a serdev or tty device depending on if the parent device has any | ||
| 180 | * defined serdev clients or not. | ||
| 181 | */ | ||
| 182 | struct device *tty_port_register_device_serdev(struct tty_port *port, | ||
| 183 | struct tty_driver *driver, unsigned index, | ||
| 184 | struct device *device) | ||
| 185 | { | ||
| 186 | return tty_port_register_device_attr_serdev(port, driver, index, | ||
| 187 | device, NULL, NULL); | ||
| 188 | } | ||
| 189 | EXPORT_SYMBOL_GPL(tty_port_register_device_serdev); | ||
| 190 | |||
| 191 | /** | ||
| 192 | * tty_port_unregister_device - deregister a tty or serdev device | ||
| 193 | * @port: tty_port of the device | ||
| 194 | * @driver: tty_driver for this device | ||
| 195 | * @index: index of the tty | ||
| 196 | * | ||
| 197 | * If a tty or serdev device is registered with a call to | ||
| 198 | * tty_port_register_device_serdev() then this function must be called when | ||
| 199 | * the device is gone. | ||
| 200 | */ | ||
| 201 | void tty_port_unregister_device(struct tty_port *port, | ||
| 202 | struct tty_driver *driver, unsigned index) | ||
| 203 | { | ||
| 204 | int ret; | ||
| 205 | |||
| 206 | ret = serdev_tty_port_unregister(port); | ||
| 207 | if (ret == 0) | ||
| 208 | return; | ||
| 209 | |||
| 210 | tty_unregister_device(driver, index); | ||
| 211 | } | ||
| 212 | EXPORT_SYMBOL_GPL(tty_port_unregister_device); | ||
| 145 | 213 | ||
| 146 | int tty_port_alloc_xmit_buf(struct tty_port *port) | 214 | int tty_port_alloc_xmit_buf(struct tty_port *port) |
| 147 | { | 215 | { |
| @@ -189,9 +257,6 @@ static void tty_port_destructor(struct kref *kref) | |||
| 189 | /* check if last port ref was dropped before tty release */ | 257 | /* check if last port ref was dropped before tty release */ |
| 190 | if (WARN_ON(port->itty)) | 258 | if (WARN_ON(port->itty)) |
| 191 | return; | 259 | return; |
| 192 | |||
| 193 | serdev_tty_port_unregister(port); | ||
| 194 | |||
| 195 | if (port->xmit_buf) | 260 | if (port->xmit_buf) |
| 196 | free_page((unsigned long)port->xmit_buf); | 261 | free_page((unsigned long)port->xmit_buf); |
| 197 | tty_port_destroy(port); | 262 | tty_port_destroy(port); |
