diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/tty/hvc/hvc_dcc.c | 2 | ||||
| -rw-r--r-- | drivers/tty/serial/Kconfig | 14 | ||||
| -rw-r--r-- | drivers/tty/serial/atmel_serial.c | 16 | ||||
| -rw-r--r-- | drivers/tty/serial/crisv10.c | 10 | ||||
| -rw-r--r-- | drivers/tty/serial/mfd.c | 4 | ||||
| -rw-r--r-- | drivers/tty/serial/pch_uart.c | 19 | ||||
| -rw-r--r-- | drivers/tty/tty_ldisc.c | 30 |
7 files changed, 52 insertions, 43 deletions
diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c index 435f6facbc23..44fbebab5075 100644 --- a/drivers/tty/hvc/hvc_dcc.c +++ b/drivers/tty/hvc/hvc_dcc.c | |||
| @@ -46,6 +46,7 @@ static inline char __dcc_getchar(void) | |||
| 46 | 46 | ||
| 47 | asm volatile("mrc p14, 0, %0, c0, c5, 0 @ read comms data reg" | 47 | asm volatile("mrc p14, 0, %0, c0, c5, 0 @ read comms data reg" |
| 48 | : "=r" (__c)); | 48 | : "=r" (__c)); |
| 49 | isb(); | ||
| 49 | 50 | ||
| 50 | return __c; | 51 | return __c; |
| 51 | } | 52 | } |
| @@ -55,6 +56,7 @@ static inline void __dcc_putchar(char c) | |||
| 55 | asm volatile("mcr p14, 0, %0, c0, c5, 0 @ write a char" | 56 | asm volatile("mcr p14, 0, %0, c0, c5, 0 @ write a char" |
| 56 | : /* no output register */ | 57 | : /* no output register */ |
| 57 | : "r" (c)); | 58 | : "r" (c)); |
| 59 | isb(); | ||
| 58 | } | 60 | } |
| 59 | 61 | ||
| 60 | static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count) | 62 | static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count) |
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 5f479dada6f2..925a1e547a83 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
| @@ -1560,7 +1560,7 @@ config SERIAL_IFX6X60 | |||
| 1560 | Support for the IFX6x60 modem devices on Intel MID platforms. | 1560 | Support for the IFX6x60 modem devices on Intel MID platforms. |
| 1561 | 1561 | ||
| 1562 | config SERIAL_PCH_UART | 1562 | config SERIAL_PCH_UART |
| 1563 | tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) UART" | 1563 | tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) UART" |
| 1564 | depends on PCI | 1564 | depends on PCI |
| 1565 | select SERIAL_CORE | 1565 | select SERIAL_CORE |
| 1566 | help | 1566 | help |
| @@ -1568,12 +1568,12 @@ config SERIAL_PCH_UART | |||
| 1568 | which is an IOH(Input/Output Hub) for x86 embedded processor. | 1568 | which is an IOH(Input/Output Hub) for x86 embedded processor. |
| 1569 | Enabling PCH_DMA, this PCH UART works as DMA mode. | 1569 | Enabling PCH_DMA, this PCH UART works as DMA mode. |
| 1570 | 1570 | ||
| 1571 | This driver also can be used for OKI SEMICONDUCTOR IOH(Input/ | 1571 | This driver also can be used for LAPIS Semiconductor IOH(Input/ |
| 1572 | Output Hub), ML7213 and ML7223. | 1572 | Output Hub), ML7213, ML7223 and ML7831. |
| 1573 | ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is | 1573 | ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is |
| 1574 | for MP(Media Phone) use. | 1574 | for MP(Media Phone) use and ML7831 IOH is for general purpose use. |
| 1575 | ML7213/ML7223 is companion chip for Intel Atom E6xx series. | 1575 | ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. |
| 1576 | ML7213/ML7223 is completely compatible for Intel EG20T PCH. | 1576 | ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. |
| 1577 | 1577 | ||
| 1578 | config SERIAL_MSM_SMD | 1578 | config SERIAL_MSM_SMD |
| 1579 | bool "Enable tty device interface for some SMD ports" | 1579 | bool "Enable tty device interface for some SMD ports" |
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 4a0f86fa1e90..4c823f341d98 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
| @@ -228,7 +228,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) | |||
| 228 | if (rs485conf->flags & SER_RS485_ENABLED) { | 228 | if (rs485conf->flags & SER_RS485_ENABLED) { |
| 229 | dev_dbg(port->dev, "Setting UART to RS485\n"); | 229 | dev_dbg(port->dev, "Setting UART to RS485\n"); |
| 230 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; | 230 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; |
| 231 | if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND) | 231 | if ((rs485conf->delay_rts_after_send) > 0) |
| 232 | UART_PUT_TTGR(port, rs485conf->delay_rts_after_send); | 232 | UART_PUT_TTGR(port, rs485conf->delay_rts_after_send); |
| 233 | mode |= ATMEL_US_USMODE_RS485; | 233 | mode |= ATMEL_US_USMODE_RS485; |
| 234 | } else { | 234 | } else { |
| @@ -304,7 +304,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) | |||
| 304 | 304 | ||
| 305 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | 305 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { |
| 306 | dev_dbg(port->dev, "Setting UART to RS485\n"); | 306 | dev_dbg(port->dev, "Setting UART to RS485\n"); |
| 307 | if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) | 307 | if ((atmel_port->rs485.delay_rts_after_send) > 0) |
| 308 | UART_PUT_TTGR(port, | 308 | UART_PUT_TTGR(port, |
| 309 | atmel_port->rs485.delay_rts_after_send); | 309 | atmel_port->rs485.delay_rts_after_send); |
| 310 | mode |= ATMEL_US_USMODE_RS485; | 310 | mode |= ATMEL_US_USMODE_RS485; |
| @@ -1228,7 +1228,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1228 | 1228 | ||
| 1229 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | 1229 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { |
| 1230 | dev_dbg(port->dev, "Setting UART to RS485\n"); | 1230 | dev_dbg(port->dev, "Setting UART to RS485\n"); |
| 1231 | if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) | 1231 | if ((atmel_port->rs485.delay_rts_after_send) > 0) |
| 1232 | UART_PUT_TTGR(port, | 1232 | UART_PUT_TTGR(port, |
| 1233 | atmel_port->rs485.delay_rts_after_send); | 1233 | atmel_port->rs485.delay_rts_after_send); |
| 1234 | mode |= ATMEL_US_USMODE_RS485; | 1234 | mode |= ATMEL_US_USMODE_RS485; |
| @@ -1447,16 +1447,6 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port, | |||
| 1447 | rs485conf->delay_rts_after_send = rs485_delay[1]; | 1447 | rs485conf->delay_rts_after_send = rs485_delay[1]; |
| 1448 | rs485conf->flags = 0; | 1448 | rs485conf->flags = 0; |
| 1449 | 1449 | ||
| 1450 | if (rs485conf->delay_rts_before_send == 0 && | ||
| 1451 | rs485conf->delay_rts_after_send == 0) { | ||
| 1452 | rs485conf->flags |= SER_RS485_RTS_ON_SEND; | ||
| 1453 | } else { | ||
| 1454 | if (rs485conf->delay_rts_before_send) | ||
| 1455 | rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND; | ||
| 1456 | if (rs485conf->delay_rts_after_send) | ||
| 1457 | rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; | ||
| 1458 | } | ||
| 1459 | |||
| 1460 | if (of_get_property(np, "rs485-rx-during-tx", NULL)) | 1450 | if (of_get_property(np, "rs485-rx-during-tx", NULL)) |
| 1461 | rs485conf->flags |= SER_RS485_RX_DURING_TX; | 1451 | rs485conf->flags |= SER_RS485_RX_DURING_TX; |
| 1462 | 1452 | ||
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index b7435043f2fe..1dfba7b779c8 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c | |||
| @@ -3234,9 +3234,8 @@ rs_write(struct tty_struct *tty, | |||
| 3234 | e100_disable_rx(info); | 3234 | e100_disable_rx(info); |
| 3235 | e100_enable_rx_irq(info); | 3235 | e100_enable_rx_irq(info); |
| 3236 | #endif | 3236 | #endif |
| 3237 | if ((info->rs485.flags & SER_RS485_RTS_BEFORE_SEND) && | 3237 | if (info->rs485.delay_rts_before_send > 0) |
| 3238 | (info->rs485.delay_rts_before_send > 0)) | 3238 | msleep(info->rs485.delay_rts_before_send); |
| 3239 | msleep(info->rs485.delay_rts_before_send); | ||
| 3240 | } | 3239 | } |
| 3241 | #endif /* CONFIG_ETRAX_RS485 */ | 3240 | #endif /* CONFIG_ETRAX_RS485 */ |
| 3242 | 3241 | ||
| @@ -3693,10 +3692,6 @@ rs_ioctl(struct tty_struct *tty, | |||
| 3693 | 3692 | ||
| 3694 | rs485data.delay_rts_before_send = rs485ctrl.delay_rts_before_send; | 3693 | rs485data.delay_rts_before_send = rs485ctrl.delay_rts_before_send; |
| 3695 | rs485data.flags = 0; | 3694 | rs485data.flags = 0; |
| 3696 | if (rs485data.delay_rts_before_send != 0) | ||
| 3697 | rs485data.flags |= SER_RS485_RTS_BEFORE_SEND; | ||
| 3698 | else | ||
| 3699 | rs485data.flags &= ~(SER_RS485_RTS_BEFORE_SEND); | ||
| 3700 | 3695 | ||
| 3701 | if (rs485ctrl.enabled) | 3696 | if (rs485ctrl.enabled) |
| 3702 | rs485data.flags |= SER_RS485_ENABLED; | 3697 | rs485data.flags |= SER_RS485_ENABLED; |
| @@ -4531,7 +4526,6 @@ static int __init rs_init(void) | |||
| 4531 | /* Set sane defaults */ | 4526 | /* Set sane defaults */ |
| 4532 | info->rs485.flags &= ~(SER_RS485_RTS_ON_SEND); | 4527 | info->rs485.flags &= ~(SER_RS485_RTS_ON_SEND); |
| 4533 | info->rs485.flags |= SER_RS485_RTS_AFTER_SEND; | 4528 | info->rs485.flags |= SER_RS485_RTS_AFTER_SEND; |
| 4534 | info->rs485.flags &= ~(SER_RS485_RTS_BEFORE_SEND); | ||
| 4535 | info->rs485.delay_rts_before_send = 0; | 4529 | info->rs485.delay_rts_before_send = 0; |
| 4536 | info->rs485.flags &= ~(SER_RS485_ENABLED); | 4530 | info->rs485.flags &= ~(SER_RS485_ENABLED); |
| 4537 | #endif | 4531 | #endif |
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index 286c386d9c46..e272d3919c67 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c | |||
| @@ -884,7 +884,6 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 884 | { | 884 | { |
| 885 | struct uart_hsu_port *up = | 885 | struct uart_hsu_port *up = |
| 886 | container_of(port, struct uart_hsu_port, port); | 886 | container_of(port, struct uart_hsu_port, port); |
| 887 | struct tty_struct *tty = port->state->port.tty; | ||
| 888 | unsigned char cval, fcr = 0; | 887 | unsigned char cval, fcr = 0; |
| 889 | unsigned long flags; | 888 | unsigned long flags; |
| 890 | unsigned int baud, quot; | 889 | unsigned int baud, quot; |
| @@ -907,8 +906,7 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 907 | } | 906 | } |
| 908 | 907 | ||
| 909 | /* CMSPAR isn't supported by this driver */ | 908 | /* CMSPAR isn't supported by this driver */ |
| 910 | if (tty) | 909 | termios->c_cflag &= ~CMSPAR; |
| 911 | tty->termios->c_cflag &= ~CMSPAR; | ||
| 912 | 910 | ||
| 913 | if (termios->c_cflag & CSTOPB) | 911 | if (termios->c_cflag & CSTOPB) |
| 914 | cval |= UART_LCR_STOP; | 912 | cval |= UART_LCR_STOP; |
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 21febef926aa..d6aba8c087e4 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | *Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD. | 2 | *Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. |
| 3 | * | 3 | * |
| 4 | *This program is free software; you can redistribute it and/or modify | 4 | *This program is free software; you can redistribute it and/or modify |
| 5 | *it under the terms of the GNU General Public License as published by | 5 | *it under the terms of the GNU General Public License as published by |
| @@ -46,8 +46,8 @@ enum { | |||
| 46 | 46 | ||
| 47 | /* Set the max number of UART port | 47 | /* Set the max number of UART port |
| 48 | * Intel EG20T PCH: 4 port | 48 | * Intel EG20T PCH: 4 port |
| 49 | * OKI SEMICONDUCTOR ML7213 IOH: 3 port | 49 | * LAPIS Semiconductor ML7213 IOH: 3 port |
| 50 | * OKI SEMICONDUCTOR ML7223 IOH: 2 port | 50 | * LAPIS Semiconductor ML7223 IOH: 2 port |
| 51 | */ | 51 | */ |
| 52 | #define PCH_UART_NR 4 | 52 | #define PCH_UART_NR 4 |
| 53 | 53 | ||
| @@ -258,6 +258,8 @@ enum pch_uart_num_t { | |||
| 258 | pch_ml7213_uart2, | 258 | pch_ml7213_uart2, |
| 259 | pch_ml7223_uart0, | 259 | pch_ml7223_uart0, |
| 260 | pch_ml7223_uart1, | 260 | pch_ml7223_uart1, |
| 261 | pch_ml7831_uart0, | ||
| 262 | pch_ml7831_uart1, | ||
| 261 | }; | 263 | }; |
| 262 | 264 | ||
| 263 | static struct pch_uart_driver_data drv_dat[] = { | 265 | static struct pch_uart_driver_data drv_dat[] = { |
| @@ -270,6 +272,8 @@ static struct pch_uart_driver_data drv_dat[] = { | |||
| 270 | [pch_ml7213_uart2] = {PCH_UART_2LINE, 2}, | 272 | [pch_ml7213_uart2] = {PCH_UART_2LINE, 2}, |
| 271 | [pch_ml7223_uart0] = {PCH_UART_8LINE, 0}, | 273 | [pch_ml7223_uart0] = {PCH_UART_8LINE, 0}, |
| 272 | [pch_ml7223_uart1] = {PCH_UART_2LINE, 1}, | 274 | [pch_ml7223_uart1] = {PCH_UART_2LINE, 1}, |
| 275 | [pch_ml7831_uart0] = {PCH_UART_8LINE, 0}, | ||
| 276 | [pch_ml7831_uart1] = {PCH_UART_2LINE, 1}, | ||
| 273 | }; | 277 | }; |
| 274 | 278 | ||
| 275 | static unsigned int default_baud = 9600; | 279 | static unsigned int default_baud = 9600; |
| @@ -628,6 +632,7 @@ static void pch_request_dma(struct uart_port *port) | |||
| 628 | dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n", | 632 | dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n", |
| 629 | __func__); | 633 | __func__); |
| 630 | dma_release_channel(priv->chan_tx); | 634 | dma_release_channel(priv->chan_tx); |
| 635 | priv->chan_tx = NULL; | ||
| 631 | return; | 636 | return; |
| 632 | } | 637 | } |
| 633 | 638 | ||
| @@ -1215,8 +1220,7 @@ static void pch_uart_shutdown(struct uart_port *port) | |||
| 1215 | dev_err(priv->port.dev, | 1220 | dev_err(priv->port.dev, |
| 1216 | "pch_uart_hal_set_fifo Failed(ret=%d)\n", ret); | 1221 | "pch_uart_hal_set_fifo Failed(ret=%d)\n", ret); |
| 1217 | 1222 | ||
| 1218 | if (priv->use_dma_flag) | 1223 | pch_free_dma(port); |
| 1219 | pch_free_dma(port); | ||
| 1220 | 1224 | ||
| 1221 | free_irq(priv->port.irq, priv); | 1225 | free_irq(priv->port.irq, priv); |
| 1222 | } | 1226 | } |
| @@ -1280,6 +1284,7 @@ static void pch_uart_set_termios(struct uart_port *port, | |||
| 1280 | if (rtn) | 1284 | if (rtn) |
| 1281 | goto out; | 1285 | goto out; |
| 1282 | 1286 | ||
| 1287 | pch_uart_set_mctrl(&priv->port, priv->port.mctrl); | ||
| 1283 | /* Don't rewrite B0 */ | 1288 | /* Don't rewrite B0 */ |
| 1284 | if (tty_termios_baud_rate(termios)) | 1289 | if (tty_termios_baud_rate(termios)) |
| 1285 | tty_termios_encode_baud_rate(termios, baud, baud); | 1290 | tty_termios_encode_baud_rate(termios, baud, baud); |
| @@ -1552,6 +1557,10 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = { | |||
| 1552 | .driver_data = pch_ml7223_uart0}, | 1557 | .driver_data = pch_ml7223_uart0}, |
| 1553 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D), | 1558 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D), |
| 1554 | .driver_data = pch_ml7223_uart1}, | 1559 | .driver_data = pch_ml7223_uart1}, |
| 1560 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8811), | ||
| 1561 | .driver_data = pch_ml7831_uart0}, | ||
| 1562 | {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8812), | ||
| 1563 | .driver_data = pch_ml7831_uart1}, | ||
| 1555 | {0,}, | 1564 | {0,}, |
| 1556 | }; | 1565 | }; |
| 1557 | 1566 | ||
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 512c49f98e85..8e0924f55446 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | #include <linux/kmod.h> | 37 | #include <linux/kmod.h> |
| 38 | #include <linux/nsproxy.h> | 38 | #include <linux/nsproxy.h> |
| 39 | #include <linux/ratelimit.h> | ||
| 39 | 40 | ||
| 40 | /* | 41 | /* |
| 41 | * This guards the refcounted line discipline lists. The lock | 42 | * This guards the refcounted line discipline lists. The lock |
| @@ -547,15 +548,16 @@ static void tty_ldisc_flush_works(struct tty_struct *tty) | |||
| 547 | /** | 548 | /** |
| 548 | * tty_ldisc_wait_idle - wait for the ldisc to become idle | 549 | * tty_ldisc_wait_idle - wait for the ldisc to become idle |
| 549 | * @tty: tty to wait for | 550 | * @tty: tty to wait for |
| 551 | * @timeout: for how long to wait at most | ||
| 550 | * | 552 | * |
| 551 | * Wait for the line discipline to become idle. The discipline must | 553 | * Wait for the line discipline to become idle. The discipline must |
| 552 | * have been halted for this to guarantee it remains idle. | 554 | * have been halted for this to guarantee it remains idle. |
| 553 | */ | 555 | */ |
| 554 | static int tty_ldisc_wait_idle(struct tty_struct *tty) | 556 | static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) |
| 555 | { | 557 | { |
| 556 | int ret; | 558 | long ret; |
| 557 | ret = wait_event_timeout(tty_ldisc_idle, | 559 | ret = wait_event_timeout(tty_ldisc_idle, |
| 558 | atomic_read(&tty->ldisc->users) == 1, 5 * HZ); | 560 | atomic_read(&tty->ldisc->users) == 1, timeout); |
| 559 | if (ret < 0) | 561 | if (ret < 0) |
| 560 | return ret; | 562 | return ret; |
| 561 | return ret > 0 ? 0 : -EBUSY; | 563 | return ret > 0 ? 0 : -EBUSY; |
| @@ -665,7 +667,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
| 665 | 667 | ||
| 666 | tty_ldisc_flush_works(tty); | 668 | tty_ldisc_flush_works(tty); |
| 667 | 669 | ||
| 668 | retval = tty_ldisc_wait_idle(tty); | 670 | retval = tty_ldisc_wait_idle(tty, 5 * HZ); |
| 669 | 671 | ||
| 670 | tty_lock(); | 672 | tty_lock(); |
| 671 | mutex_lock(&tty->ldisc_mutex); | 673 | mutex_lock(&tty->ldisc_mutex); |
| @@ -762,8 +764,6 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) | |||
| 762 | if (IS_ERR(ld)) | 764 | if (IS_ERR(ld)) |
| 763 | return -1; | 765 | return -1; |
| 764 | 766 | ||
| 765 | WARN_ON_ONCE(tty_ldisc_wait_idle(tty)); | ||
| 766 | |||
| 767 | tty_ldisc_close(tty, tty->ldisc); | 767 | tty_ldisc_close(tty, tty->ldisc); |
| 768 | tty_ldisc_put(tty->ldisc); | 768 | tty_ldisc_put(tty->ldisc); |
| 769 | tty->ldisc = NULL; | 769 | tty->ldisc = NULL; |
| @@ -838,7 +838,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
| 838 | tty_unlock(); | 838 | tty_unlock(); |
| 839 | cancel_work_sync(&tty->buf.work); | 839 | cancel_work_sync(&tty->buf.work); |
| 840 | mutex_unlock(&tty->ldisc_mutex); | 840 | mutex_unlock(&tty->ldisc_mutex); |
| 841 | 841 | retry: | |
| 842 | tty_lock(); | 842 | tty_lock(); |
| 843 | mutex_lock(&tty->ldisc_mutex); | 843 | mutex_lock(&tty->ldisc_mutex); |
| 844 | 844 | ||
| @@ -847,6 +847,22 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
| 847 | it means auditing a lot of other paths so this is | 847 | it means auditing a lot of other paths so this is |
| 848 | a FIXME */ | 848 | a FIXME */ |
| 849 | if (tty->ldisc) { /* Not yet closed */ | 849 | if (tty->ldisc) { /* Not yet closed */ |
| 850 | if (atomic_read(&tty->ldisc->users) != 1) { | ||
| 851 | char cur_n[TASK_COMM_LEN], tty_n[64]; | ||
| 852 | long timeout = 3 * HZ; | ||
| 853 | tty_unlock(); | ||
| 854 | |||
| 855 | while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { | ||
| 856 | timeout = MAX_SCHEDULE_TIMEOUT; | ||
| 857 | printk_ratelimited(KERN_WARNING | ||
| 858 | "%s: waiting (%s) for %s took too long, but we keep waiting...\n", | ||
| 859 | __func__, get_task_comm(cur_n, current), | ||
| 860 | tty_name(tty, tty_n)); | ||
| 861 | } | ||
| 862 | mutex_unlock(&tty->ldisc_mutex); | ||
| 863 | goto retry; | ||
| 864 | } | ||
| 865 | |||
| 850 | if (reset == 0) { | 866 | if (reset == 0) { |
| 851 | 867 | ||
| 852 | if (!tty_ldisc_reinit(tty, tty->termios->c_line)) | 868 | if (!tty_ldisc_reinit(tty, tty->termios->c_line)) |
