mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 23:45:31 +08:00
205d300aea
We have a number of "uart.port->desc.lock vs desc.lock->uart.port"
lockdep reports coming from 8250 driver; this causes a bit of trouble
to people, so let's fix it.
The problem is reverse lock order in two different call paths:
chain #1:
serial8250_do_startup()
spin_lock_irqsave(&port->lock);
disable_irq_nosync(port->irq);
raw_spin_lock_irqsave(&desc->lock)
chain #2:
__report_bad_irq()
raw_spin_lock_irqsave(&desc->lock)
for_each_action_of_desc()
printk()
spin_lock_irqsave(&port->lock);
Fix this by changing the order of locks in serial8250_do_startup():
do disable_irq_nosync() first, which grabs desc->lock, and grab
uart->port after that, so that chain #1 and chain #2 have same lock
order.
Full lockdep splat:
======================================================
WARNING: possible circular locking dependency detected
5.4.39 #55 Not tainted
======================================================
swapper/0/0 is trying to acquire lock:
ffffffffab65b6c0 (console_owner){-...}, at: console_lock_spinning_enable+0x31/0x57
but task is already holding lock:
ffff88810a8e34c0 (&irq_desc_lock_class){-.-.}, at: __report_bad_irq+0x5b/0xba
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (&irq_desc_lock_class){-.-.}:
_raw_spin_lock_irqsave+0x61/0x8d
__irq_get_desc_lock+0x65/0x89
__disable_irq_nosync+0x3b/0x93
serial8250_do_startup+0x451/0x75c
uart_startup+0x1b4/0x2ff
uart_port_activate+0x73/0xa0
tty_port_open+0xae/0x10a
uart_open+0x1b/0x26
tty_open+0x24d/0x3a0
chrdev_open+0xd5/0x1cc
do_dentry_open+0x299/0x3c8
path_openat+0x434/0x1100
do_filp_open+0x9b/0x10a
do_sys_open+0x15f/0x3d7
kernel_init_freeable+0x157/0x1dd
kernel_init+0xe/0x105
ret_from_fork+0x27/0x50
-> #1 (&port_lock_key){-.-.}:
_raw_spin_lock_irqsave+0x61/0x8d
serial8250_console_write+0xa7/0x2a0
console_unlock+0x3b7/0x528
vprintk_emit+0x111/0x17f
printk+0x59/0x73
register_console+0x336/0x3a4
uart_add_one_port+0x51b/0x5be
serial8250_register_8250_port+0x454/0x55e
dw8250_probe+0x4dc/0x5b9
platform_drv_probe+0x67/0x8b
really_probe+0x14a/0x422
driver_probe_device+0x66/0x130
device_driver_attach+0x42/0x5b
__driver_attach+0xca/0x139
bus_for_each_dev+0x97/0xc9
bus_add_driver+0x12b/0x228
driver_register+0x64/0xed
do_one_initcall+0x20c/0x4a6
do_initcall_level+0xb5/0xc5
do_basic_setup+0x4c/0x58
kernel_init_freeable+0x13f/0x1dd
kernel_init+0xe/0x105
ret_from_fork+0x27/0x50
-> #0 (console_owner){-...}:
__lock_acquire+0x118d/0x2714
lock_acquire+0x203/0x258
console_lock_spinning_enable+0x51/0x57
console_unlock+0x25d/0x528
vprintk_emit+0x111/0x17f
printk+0x59/0x73
__report_bad_irq+0xa3/0xba
note_interrupt+0x19a/0x1d6
handle_irq_event_percpu+0x57/0x79
handle_irq_event+0x36/0x55
handle_fasteoi_irq+0xc2/0x18a
do_IRQ+0xb3/0x157
ret_from_intr+0x0/0x1d
cpuidle_enter_state+0x12f/0x1fd
cpuidle_enter+0x2e/0x3d
do_idle+0x1ce/0x2ce
cpu_startup_entry+0x1d/0x1f
start_kernel+0x406/0x46a
secondary_startup_64+0xa4/0xb0
other info that might help us debug this:
Chain exists of:
console_owner --> &port_lock_key --> &irq_desc_lock_class
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&irq_desc_lock_class);
lock(&port_lock_key);
lock(&irq_desc_lock_class);
lock(console_owner);
*** DEADLOCK ***
2 locks held by swapper/0/0:
#0: ffff88810a8e34c0 (&irq_desc_lock_class){-.-.}, at: __report_bad_irq+0x5b/0xba
#1: ffffffffab65b5c0 (console_lock){+.+.}, at: console_trylock_spinning+0x20/0x181
stack backtrace:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.39 #55
Hardware name: XXXXXX
Call Trace:
<IRQ>
dump_stack+0xbf/0x133
? print_circular_bug+0xd6/0xe9
check_noncircular+0x1b9/0x1c3
__lock_acquire+0x118d/0x2714
lock_acquire+0x203/0x258
? console_lock_spinning_enable+0x31/0x57
console_lock_spinning_enable+0x51/0x57
? console_lock_spinning_enable+0x31/0x57
console_unlock+0x25d/0x528
? console_trylock+0x18/0x4e
vprintk_emit+0x111/0x17f
? lock_acquire+0x203/0x258
printk+0x59/0x73
__report_bad_irq+0xa3/0xba
note_interrupt+0x19a/0x1d6
handle_irq_event_percpu+0x57/0x79
handle_irq_event+0x36/0x55
handle_fasteoi_irq+0xc2/0x18a
do_IRQ+0xb3/0x157
common_interrupt+0xf/0xf
</IRQ>
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Fixes:
|
||
---|---|---|
.. | ||
8250 | ||
cpm_uart | ||
jsm | ||
21285.c | ||
altera_jtaguart.c | ||
altera_uart.c | ||
amba-pl010.c | ||
amba-pl011.c | ||
amba-pl011.h | ||
apbuart.c | ||
apbuart.h | ||
ar933x_uart.c | ||
arc_uart.c | ||
atmel_serial.c | ||
atmel_serial.h | ||
bcm63xx_uart.c | ||
clps711x.c | ||
digicolor-usart.c | ||
dz.c | ||
dz.h | ||
earlycon-arm-semihost.c | ||
earlycon-riscv-sbi.c | ||
earlycon.c | ||
efm32-uart.c | ||
fsl_linflexuart.c | ||
fsl_lpuart.c | ||
icom.c | ||
icom.h | ||
ifx6x60.c | ||
ifx6x60.h | ||
imx_earlycon.c | ||
imx.c | ||
ip22zilog.c | ||
ip22zilog.h | ||
Kconfig | ||
kgdb_nmi.c | ||
kgdboc.c | ||
lantiq.c | ||
lpc32xx_hs.c | ||
Makefile | ||
max310x.c | ||
max3100.c | ||
mcf.c | ||
men_z135_uart.c | ||
meson_uart.c | ||
milbeaut_usio.c | ||
mpc52xx_uart.c | ||
mps2-uart.c | ||
msm_serial.c | ||
mux.c | ||
mvebu-uart.c | ||
mxs-auart.c | ||
omap-serial.c | ||
owl-uart.c | ||
pch_uart.c | ||
pic32_uart.c | ||
pic32_uart.h | ||
pmac_zilog.c | ||
pmac_zilog.h | ||
pnx8xxx_uart.c | ||
pxa.c | ||
qcom_geni_serial.c | ||
rda-uart.c | ||
rp2.c | ||
sa1100.c | ||
samsung_tty.c | ||
sb1250-duart.c | ||
sc16is7xx.c | ||
sccnxp.c | ||
serial_core.c | ||
serial_mctrl_gpio.c | ||
serial_mctrl_gpio.h | ||
serial_txx9.c | ||
serial-tegra.c | ||
sh-sci.c | ||
sh-sci.h | ||
sifive.c | ||
sirfsoc_uart.c | ||
sirfsoc_uart.h | ||
sprd_serial.c | ||
st-asc.c | ||
stm32-usart.c | ||
stm32-usart.h | ||
suncore.c | ||
sunhv.c | ||
sunsab.c | ||
sunsab.h | ||
sunsu.c | ||
sunzilog.c | ||
sunzilog.h | ||
tegra-tcu.c | ||
timbuart.c | ||
timbuart.h | ||
uartlite.c | ||
ucc_uart.c | ||
vr41xx_siu.c | ||
vt8500_serial.c | ||
xilinx_uartps.c | ||
zs.c | ||
zs.h |