While closing, new rx data may be received after the input buffers
have been flushed but before stop_rx() halts receiving [1]. The
new data might not be processed by flush_to_ldisc() until after
uart_shutdown() and normal input processing is re-enabled (ie.,
tty->closing = 0). The race is outlined below:
CPU 0 | CPU 1
|
uart_close() |
tty_port_close_start() |
tty->closing = 1 |
tty_ldisc_flush() |
| => IRQ
| while (LSR & data ready)
| uart_insert_char()
| tty_flip_buffer_push()
| <= EOI
stop_rx() | .
uart_shutdown() | .
free xmit.buf | .
tty_port_tty_set(NULL) | .
tty->closing = 0 | .
| flush_to_ldisc()
| n_tty_receive_buf_common()
| __receive_buf()
| ...
| commit_echoes()
| uart_flush_chars()
| __uart_start()
| ** OOPS on port.tty deref **
tty_ldisc_flush() |
Input processing must be prevented from echoing (tty->closing = 1)
until _after_ the input buffers have been flushed again at the end
of uart_close().
[1] In fact, some input may actually be buffered _after_ stop_rx()
since the rx interrupt may have already triggered but not yet been
handled when stop_rx() disables rx interrupts.
Fixes:
|
||
|---|---|---|
| .. | ||
| 8250 | ||
| cpm_uart | ||
| jsm | ||
| 21285.c | ||
| 68328serial.c | ||
| Kconfig | ||
| Makefile | ||
| altera_jtaguart.c | ||
| altera_uart.c | ||
| amba-pl010.c | ||
| amba-pl011.c | ||
| apbuart.c | ||
| apbuart.h | ||
| ar933x_uart.c | ||
| arc_uart.c | ||
| atmel_serial.c | ||
| bcm63xx_uart.c | ||
| bfin_sport_uart.c | ||
| bfin_sport_uart.h | ||
| bfin_uart.c | ||
| clps711x.c | ||
| crisv10.c | ||
| crisv10.h | ||
| digicolor-usart.c | ||
| dz.c | ||
| dz.h | ||
| earlycon-arm-semihost.c | ||
| earlycon.c | ||
| efm32-uart.c | ||
| etraxfs-uart.c | ||
| fsl_lpuart.c | ||
| icom.c | ||
| icom.h | ||
| ifx6x60.c | ||
| ifx6x60.h | ||
| imx.c | ||
| ioc3_serial.c | ||
| ioc4_serial.c | ||
| ip22zilog.c | ||
| ip22zilog.h | ||
| kgdb_nmi.c | ||
| kgdboc.c | ||
| lantiq.c | ||
| lpc32xx_hs.c | ||
| m32r_sio.c | ||
| m32r_sio.h | ||
| m32r_sio_reg.h | ||
| max310x.c | ||
| max3100.c | ||
| mcf.c | ||
| men_z135_uart.c | ||
| meson_uart.c | ||
| mpc52xx_uart.c | ||
| mpsc.c | ||
| msm_serial.c | ||
| msm_serial.h | ||
| mux.c | ||
| mxs-auart.c | ||
| netx-serial.c | ||
| nwpserial.c | ||
| of_serial.c | ||
| omap-serial.c | ||
| pch_uart.c | ||
| pmac_zilog.c | ||
| pmac_zilog.h | ||
| pnx8xxx_uart.c | ||
| pxa.c | ||
| rp2.c | ||
| sa1100.c | ||
| samsung.c | ||
| samsung.h | ||
| sb1250-duart.c | ||
| sc16is7xx.c | ||
| sccnxp.c | ||
| serial-tegra.c | ||
| serial_core.c | ||
| serial_ks8695.c | ||
| serial_mctrl_gpio.c | ||
| serial_mctrl_gpio.h | ||
| serial_txx9.c | ||
| sh-sci.c | ||
| sh-sci.h | ||
| sirfsoc_uart.c | ||
| sirfsoc_uart.h | ||
| sn_console.c | ||
| sprd_serial.c | ||
| st-asc.c | ||
| stm32-usart.c | ||
| suncore.c | ||
| sunhv.c | ||
| sunsab.c | ||
| sunsab.h | ||
| sunsu.c | ||
| sunzilog.c | ||
| sunzilog.h | ||
| tilegx.c | ||
| timbuart.c | ||
| timbuart.h | ||
| uartlite.c | ||
| ucc_uart.c | ||
| vr41xx_siu.c | ||
| vt8500_serial.c | ||
| xilinx_uartps.c | ||
| zs.c | ||
| zs.h | ||