diff options
-rw-r--r-- | MAINTAINERS | 2 | ||||
-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 | ||||
-rw-r--r-- | include/linux/serdev.h | 19 | ||||
-rw-r--r-- | include/linux/tty.h | 9 |
14 files changed, 162 insertions, 49 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 9e984645c4b0..053c3bdd1fe5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -7143,7 +7143,7 @@ S: Maintained | |||
7143 | F: drivers/media/platform/rcar_jpu.c | 7143 | F: drivers/media/platform/rcar_jpu.c |
7144 | 7144 | ||
7145 | JSM Neo PCI based serial card | 7145 | JSM Neo PCI based serial card |
7146 | M: Gabriel Krisman Bertazi <krisman@linux.vnet.ibm.com> | 7146 | M: Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com> |
7147 | L: linux-serial@vger.kernel.org | 7147 | L: linux-serial@vger.kernel.org |
7148 | S: Maintained | 7148 | S: Maintained |
7149 | F: drivers/tty/serial/jsm/ | 7149 | F: drivers/tty/serial/jsm/ |
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); |
diff --git a/include/linux/serdev.h b/include/linux/serdev.h index cda76c6506ca..e69402d4a8ae 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h | |||
@@ -195,6 +195,7 @@ int serdev_device_open(struct serdev_device *); | |||
195 | void serdev_device_close(struct serdev_device *); | 195 | void serdev_device_close(struct serdev_device *); |
196 | unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int); | 196 | unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int); |
197 | void serdev_device_set_flow_control(struct serdev_device *, bool); | 197 | void serdev_device_set_flow_control(struct serdev_device *, bool); |
198 | int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t); | ||
198 | void serdev_device_wait_until_sent(struct serdev_device *, long); | 199 | void serdev_device_wait_until_sent(struct serdev_device *, long); |
199 | int serdev_device_get_tiocm(struct serdev_device *); | 200 | int serdev_device_get_tiocm(struct serdev_device *); |
200 | int serdev_device_set_tiocm(struct serdev_device *, int, int); | 201 | int serdev_device_set_tiocm(struct serdev_device *, int, int); |
@@ -236,6 +237,12 @@ static inline unsigned int serdev_device_set_baudrate(struct serdev_device *sdev | |||
236 | return 0; | 237 | return 0; |
237 | } | 238 | } |
238 | static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {} | 239 | static inline void serdev_device_set_flow_control(struct serdev_device *sdev, bool enable) {} |
240 | static inline int serdev_device_write_buf(struct serdev_device *serdev, | ||
241 | const unsigned char *buf, | ||
242 | size_t count) | ||
243 | { | ||
244 | return -ENODEV; | ||
245 | } | ||
239 | static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {} | 246 | static inline void serdev_device_wait_until_sent(struct serdev_device *sdev, long timeout) {} |
240 | static inline int serdev_device_get_tiocm(struct serdev_device *serdev) | 247 | static inline int serdev_device_get_tiocm(struct serdev_device *serdev) |
241 | { | 248 | { |
@@ -301,7 +308,7 @@ struct tty_driver; | |||
301 | struct device *serdev_tty_port_register(struct tty_port *port, | 308 | struct device *serdev_tty_port_register(struct tty_port *port, |
302 | struct device *parent, | 309 | struct device *parent, |
303 | struct tty_driver *drv, int idx); | 310 | struct tty_driver *drv, int idx); |
304 | void serdev_tty_port_unregister(struct tty_port *port); | 311 | int serdev_tty_port_unregister(struct tty_port *port); |
305 | #else | 312 | #else |
306 | static inline struct device *serdev_tty_port_register(struct tty_port *port, | 313 | static inline struct device *serdev_tty_port_register(struct tty_port *port, |
307 | struct device *parent, | 314 | struct device *parent, |
@@ -309,14 +316,10 @@ static inline struct device *serdev_tty_port_register(struct tty_port *port, | |||
309 | { | 316 | { |
310 | return ERR_PTR(-ENODEV); | 317 | return ERR_PTR(-ENODEV); |
311 | } | 318 | } |
312 | static inline void serdev_tty_port_unregister(struct tty_port *port) {} | 319 | static inline int serdev_tty_port_unregister(struct tty_port *port) |
313 | #endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */ | ||
314 | |||
315 | static inline int serdev_device_write_buf(struct serdev_device *serdev, | ||
316 | const unsigned char *data, | ||
317 | size_t count) | ||
318 | { | 320 | { |
319 | return serdev_device_write(serdev, data, count, 0); | 321 | return -ENODEV; |
320 | } | 322 | } |
323 | #endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */ | ||
321 | 324 | ||
322 | #endif /*_LINUX_SERDEV_H */ | 325 | #endif /*_LINUX_SERDEV_H */ |
diff --git a/include/linux/tty.h b/include/linux/tty.h index d07cd2105a6c..eccb4ec30a8a 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -558,6 +558,15 @@ extern struct device *tty_port_register_device_attr(struct tty_port *port, | |||
558 | struct tty_driver *driver, unsigned index, | 558 | struct tty_driver *driver, unsigned index, |
559 | struct device *device, void *drvdata, | 559 | struct device *device, void *drvdata, |
560 | const struct attribute_group **attr_grp); | 560 | const struct attribute_group **attr_grp); |
561 | extern struct device *tty_port_register_device_serdev(struct tty_port *port, | ||
562 | struct tty_driver *driver, unsigned index, | ||
563 | struct device *device); | ||
564 | extern struct device *tty_port_register_device_attr_serdev(struct tty_port *port, | ||
565 | struct tty_driver *driver, unsigned index, | ||
566 | struct device *device, void *drvdata, | ||
567 | const struct attribute_group **attr_grp); | ||
568 | extern void tty_port_unregister_device(struct tty_port *port, | ||
569 | struct tty_driver *driver, unsigned index); | ||
561 | extern int tty_port_alloc_xmit_buf(struct tty_port *port); | 570 | extern int tty_port_alloc_xmit_buf(struct tty_port *port); |
562 | extern void tty_port_free_xmit_buf(struct tty_port *port); | 571 | extern void tty_port_free_xmit_buf(struct tty_port *port); |
563 | extern void tty_port_destroy(struct tty_port *port); | 572 | extern void tty_port_destroy(struct tty_port *port); |