e144c58cad
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 | ||
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 | ||
Kconfig | ||
kgdb_nmi.c | ||
kgdboc.c | ||
lantiq.c | ||
lpc32xx_hs.c | ||
m32r_sio_reg.h | ||
m32r_sio.c | ||
m32r_sio.h | ||
Makefile | ||
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_core.c | ||
serial_ks8695.c | ||
serial_mctrl_gpio.c | ||
serial_mctrl_gpio.h | ||
serial_txx9.c | ||
serial-tegra.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 |