Skip to content

Commit 249f1ef

Browse files
committed
Merge tag 'tty-4.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial fixes from Greg KH: "Here are some serial and tty fixes for 4.12-rc3. They are a bit bigger than normal, which is why I had them bake in linux-next for a few weeks and didn't send them to you for -rc2. They revert a few of the serdev patches from 4.12-rc1, and bring things back to how they were in 4.11, to try to make things a bit more stable there. Rob and Johan both agree that this is the way forward, so this isn't people squabbling over semantics. Other than that, just a few minor serial driver fixes that people have had problems with. All of these have been in linux-next for a few weeks with no reported issues" * tag 'tty-4.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: serial: altera_uart: call iounmap() at driver remove serial: imx: ensure UCR3 and UFCR are setup correctly MAINTAINERS/serial: Change maintainer of jsm driver serial: enable serdev support tty/serdev: add serdev registration interface serdev: Restore serdev_device_write_buf for atomic context serial: core: fix crash in uart_suspend_port tty: fix port buffer locking tty: ehv_bytechan: clean up init error handling serial: ifx6x60: fix use-after-free on module unload serial: altera_jtaguart: adding iounmap() serial: exar: Fix stuck MSIs serial: efm32: Fix parity management in 'efm32_uart_console_get_options()' serdev: fix tty-port client deregistration Revert "tty_port: register tty ports with serdev bus" drivers/tty: 8250: only call fintek_8250_probe when doing port I/O
2 parents 6f68a6a + 59fe2cc commit 249f1ef

File tree

14 files changed

+162
-49
lines changed

14 files changed

+162
-49
lines changed

MAINTAINERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7143,7 +7143,7 @@ S: Maintained
71437143
F: drivers/media/platform/rcar_jpu.c
71447144

71457145
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>
71477147
L: linux-serial@vger.kernel.org
71487148
S: Maintained
71497149
F: drivers/tty/serial/jsm/

drivers/tty/ehv_bytechan.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ static int __init ehv_bc_init(void)
764764
ehv_bc_driver = alloc_tty_driver(count);
765765
if (!ehv_bc_driver) {
766766
ret = -ENOMEM;
767-
goto error;
767+
goto err_free_bcs;
768768
}
769769

770770
ehv_bc_driver->driver_name = "ehv-bc";
@@ -778,24 +778,23 @@ static int __init ehv_bc_init(void)
778778
ret = tty_register_driver(ehv_bc_driver);
779779
if (ret) {
780780
pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret);
781-
goto error;
781+
goto err_put_tty_driver;
782782
}
783783

784784
ret = platform_driver_register(&ehv_bc_tty_driver);
785785
if (ret) {
786786
pr_err("ehv-bc: could not register platform driver (ret=%i)\n",
787787
ret);
788-
goto error;
788+
goto err_deregister_tty_driver;
789789
}
790790

791791
return 0;
792792

793-
error:
794-
if (ehv_bc_driver) {
795-
tty_unregister_driver(ehv_bc_driver);
796-
put_tty_driver(ehv_bc_driver);
797-
}
798-
793+
err_deregister_tty_driver:
794+
tty_unregister_driver(ehv_bc_driver);
795+
err_put_tty_driver:
796+
put_tty_driver(ehv_bc_driver);
797+
err_free_bcs:
799798
kfree(bcs);
800799

801800
return ret;

drivers/tty/serdev/core.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,18 @@ void serdev_device_write_wakeup(struct serdev_device *serdev)
122122
}
123123
EXPORT_SYMBOL_GPL(serdev_device_write_wakeup);
124124

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+
125137
int serdev_device_write(struct serdev_device *serdev,
126138
const unsigned char *buf, size_t count,
127139
unsigned long timeout)

drivers/tty/serdev/serdev-ttyport.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,6 @@ static int ttyport_open(struct serdev_controller *ctrl)
102102
return PTR_ERR(tty);
103103
serport->tty = tty;
104104

105-
serport->port->client_ops = &client_ops;
106-
serport->port->client_data = ctrl;
107-
108105
if (tty->ops->open)
109106
tty->ops->open(serport->tty, NULL);
110107
else
@@ -215,6 +212,7 @@ struct device *serdev_tty_port_register(struct tty_port *port,
215212
struct device *parent,
216213
struct tty_driver *drv, int idx)
217214
{
215+
const struct tty_port_client_operations *old_ops;
218216
struct serdev_controller *ctrl;
219217
struct serport *serport;
220218
int ret;
@@ -233,28 +231,37 @@ struct device *serdev_tty_port_register(struct tty_port *port,
233231

234232
ctrl->ops = &ctrl_ops;
235233

234+
old_ops = port->client_ops;
235+
port->client_ops = &client_ops;
236+
port->client_data = ctrl;
237+
236238
ret = serdev_controller_add(ctrl);
237239
if (ret)
238-
goto err_controller_put;
240+
goto err_reset_data;
239241

240242
dev_info(&ctrl->dev, "tty port %s%d registered\n", drv->name, idx);
241243
return &ctrl->dev;
242244

243-
err_controller_put:
245+
err_reset_data:
246+
port->client_data = NULL;
247+
port->client_ops = old_ops;
244248
serdev_controller_put(ctrl);
249+
245250
return ERR_PTR(ret);
246251
}
247252

248-
void serdev_tty_port_unregister(struct tty_port *port)
253+
int serdev_tty_port_unregister(struct tty_port *port)
249254
{
250255
struct serdev_controller *ctrl = port->client_data;
251256
struct serport *serport = serdev_controller_get_drvdata(ctrl);
252257

253258
if (!serport)
254-
return;
259+
return -ENODEV;
255260

256261
serdev_controller_remove(ctrl);
257262
port->client_ops = NULL;
258263
port->client_data = NULL;
259264
serdev_controller_put(ctrl);
265+
266+
return 0;
260267
}

drivers/tty/serial/8250/8250_port.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
/*
4848
* These are definitions for the Exar XR17V35X and XR17(C|D)15X
4949
*/
50+
#define UART_EXAR_INT0 0x80
5051
#define UART_EXAR_SLEEP 0x8b /* Sleep mode */
5152
#define UART_EXAR_DVID 0x8d /* Device identification */
5253

@@ -1337,7 +1338,7 @@ static void autoconfig(struct uart_8250_port *up)
13371338
/*
13381339
* Check if the device is a Fintek F81216A
13391340
*/
1340-
if (port->type == PORT_16550A)
1341+
if (port->type == PORT_16550A && port->iotype == UPIO_PORT)
13411342
fintek_8250_probe(up);
13421343

13431344
if (up->capabilities != old_capabilities) {
@@ -1869,17 +1870,13 @@ static int serial8250_default_handle_irq(struct uart_port *port)
18691870
static int exar_handle_irq(struct uart_port *port)
18701871
{
18711872
unsigned int iir = serial_port_in(port, UART_IIR);
1872-
int ret;
1873+
int ret = 0;
18731874

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;
18751878

1876-
if ((port->type == PORT_XR17V35X) ||
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-
}
1879+
ret |= serial8250_handle_irq(port, iir);
18831880

18841881
return ret;
18851882
}
@@ -2177,6 +2174,8 @@ int serial8250_do_startup(struct uart_port *port)
21772174
serial_port_in(port, UART_RX);
21782175
serial_port_in(port, UART_IIR);
21792176
serial_port_in(port, UART_MSR);
2177+
if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
2178+
serial_port_in(port, UART_EXAR_INT0);
21802179

21812180
/*
21822181
* At this point, there's no way the LSR could still be 0xff;
@@ -2335,6 +2334,8 @@ int serial8250_do_startup(struct uart_port *port)
23352334
serial_port_in(port, UART_RX);
23362335
serial_port_in(port, UART_IIR);
23372336
serial_port_in(port, UART_MSR);
2337+
if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
2338+
serial_port_in(port, UART_EXAR_INT0);
23382339
up->lsr_saved_flags = 0;
23392340
up->msr_saved_flags = 0;
23402341

drivers/tty/serial/altera_jtaguart.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ static int altera_jtaguart_remove(struct platform_device *pdev)
478478

479479
port = &altera_jtaguart_ports[i].port;
480480
uart_remove_one_port(&altera_jtaguart_driver, port);
481+
iounmap(port->membase);
481482

482483
return 0;
483484
}

drivers/tty/serial/altera_uart.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ static int altera_uart_remove(struct platform_device *pdev)
615615
if (port) {
616616
uart_remove_one_port(&altera_uart_driver, port);
617617
port->mapbase = 0;
618+
iounmap(port->membase);
618619
}
619620

620621
return 0;

drivers/tty/serial/efm32-uart.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#define UARTn_FRAME 0x04
2828
#define UARTn_FRAME_DATABITS__MASK 0x000f
2929
#define UARTn_FRAME_DATABITS(n) ((n) - 3)
30+
#define UARTn_FRAME_PARITY__MASK 0x0300
3031
#define UARTn_FRAME_PARITY_NONE 0x0000
3132
#define UARTn_FRAME_PARITY_EVEN 0x0200
3233
#define UARTn_FRAME_PARITY_ODD 0x0300
@@ -572,12 +573,16 @@ static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port,
572573
16 * (4 + (clkdiv >> 6)));
573574

574575
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:
576578
*parity = 'o';
577-
else if (frame & UARTn_FRAME_PARITY_EVEN)
579+
break;
580+
case UARTn_FRAME_PARITY_EVEN:
578581
*parity = 'e';
579-
else
582+
break;
583+
default:
580584
*parity = 'n';
585+
}
581586

582587
*bits = (frame & UARTn_FRAME_DATABITS__MASK) -
583588
UARTn_FRAME_DATABITS(4) + 4;

drivers/tty/serial/ifx6x60.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1382,9 +1382,9 @@ static struct spi_driver ifx_spi_driver = {
13821382
static void __exit ifx_spi_exit(void)
13831383
{
13841384
/* unregister */
1385+
spi_unregister_driver(&ifx_spi_driver);
13851386
tty_unregister_driver(tty_drv);
13861387
put_tty_driver(tty_drv);
1387-
spi_unregister_driver(&ifx_spi_driver);
13881388
unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
13891389
}
13901390

drivers/tty/serial/imx.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2184,7 +2184,9 @@ static int serial_imx_probe(struct platform_device *pdev)
21842184
* and DCD (when they are outputs) or enables the respective
21852185
* irqs. So set this bit early, i.e. before requesting irqs.
21862186
*/
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);
21882190

21892191
/*
21902192
* Disable UCR3_RI and UCR3_DCD irqs. They are also not
@@ -2195,7 +2197,15 @@ static int serial_imx_probe(struct platform_device *pdev)
21952197
sport->port.membase + UCR3);
21962198

21972199
} 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);
21992209
}
22002210

22012211
clk_disable_unprepare(sport->clk_ipg);

drivers/tty/serial/serial_core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,7 +2083,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
20832083
mutex_lock(&port->mutex);
20842084

20852085
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)) {
20872087
if (!enable_irq_wake(uport->irq))
20882088
uport->irq_wake = 1;
20892089
put_device(tty_dev);
@@ -2782,7 +2782,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
27822782
* Register the port whether it's detected or not. This allows
27832783
* setserial to be used to alter this port's parameters.
27842784
*/
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,
27862786
uport->line, uport->dev, port, uport->tty_groups);
27872787
if (likely(!IS_ERR(tty_dev))) {
27882788
device_set_wakeup_capable(tty_dev, 1);
@@ -2845,7 +2845,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
28452845
/*
28462846
* Remove the devices from the tty layer
28472847
*/
2848-
tty_unregister_device(drv->tty_driver, uport->line);
2848+
tty_port_unregister_device(port, drv->tty_driver, uport->line);
28492849

28502850
tty = tty_port_tty_get(port);
28512851
if (tty) {

0 commit comments

Comments
 (0)