linux/drivers/tty/serial
Viresh Kumar 3fa1200851 tty: serial: arc: drop uart_port->lock before calling tty_flip_buffer_push()
The current driver triggers a lockdep warning for if tty_flip_buffer_push() is
called with uart_port->lock locked. This never shows up on UP kernels and comes
up only on SMP kernels.

Crash looks like this (produced with samsung.c driver):

-----
[<c0014d58>] (unwind_backtrace+0x0/0xf8) from [<c0011908>] (show_stack+0x10/0x14)
[<c0011908>] (show_stack+0x10/0x14) from [<c035da34>] (dump_stack+0x6c/0xac)
[<c035da34>] (dump_stack+0x6c/0xac) from [<c01b59ac>] (do_raw_spin_unlock+0xc4/0xd8)
[<c01b59ac>] (do_raw_spin_unlock+0xc4/0xd8) from [<c03627e4>] (_raw_spin_unlock_irqrestore+0xc/0)
[<c03627e4>] (_raw_spin_unlock_irqrestore+0xc/0x38) from [<c020a1a8>] (s3c24xx_serial_rx_chars+0)
[<c020a1a8>] (s3c24xx_serial_rx_chars+0x12c/0x260) from [<c020aae8>] (s3c64xx_serial_handle_irq+)
[<c020aae8>] (s3c64xx_serial_handle_irq+0x48/0x60) from [<c006aaa0>] (handle_irq_event_percpu+0x)
[<c006aaa0>] (handle_irq_event_percpu+0x50/0x194) from [<c006ac20>] (handle_irq_event+0x3c/0x5c)
[<c006ac20>] (handle_irq_event+0x3c/0x5c) from [<c006d864>] (handle_fasteoi_irq+0x80/0x13c)
[<c006d864>] (handle_fasteoi_irq+0x80/0x13c) from [<c006a4a4>] (generic_handle_irq+0x20/0x30)
[<c006a4a4>] (generic_handle_irq+0x20/0x30) from [<c000f454>] (handle_IRQ+0x38/0x94)
[<c000f454>] (handle_IRQ+0x38/0x94) from [<c0008538>] (gic_handle_irq+0x34/0x68)
[<c0008538>] (gic_handle_irq+0x34/0x68) from [<c00123c0>] (__irq_svc+0x40/0x70)
Exception stack(0xc04cdf70 to 0xc04cdfb8)
df60:                                     00000000 00000000 0000166e 00000000
df80: c04cc000 c050278f c050278f 00000001 c04d444c 410fc0f4 c03649b0 00000000
dfa0: 00000001 c04cdfb8 c000f758 c000f75c 60070013 ffffffff
[<c00123c0>] (__irq_svc+0x40/0x70) from [<c000f75c>] (arch_cpu_idle+0x28/0x30)
[<c000f75c>] (arch_cpu_idle+0x28/0x30) from [<c0054888>] (cpu_startup_entry+0x5c/0x148)
[<c0054888>] (cpu_startup_entry+0x5c/0x148) from [<c0497aa4>] (start_kernel+0x334/0x38c)
BUG: spinlock lockup suspected on CPU#0, kworker/0:1/360
 lock: s3c24xx_serial_ports+0x1d8/0x370, .magic: dead4ead, .owner: <none>/-1, .owner_cpu: -1
CPU: 0 PID: 360 Comm: kworker/0:1 Not tainted 3.11.0-rc6-next-20130819-00003-g75485f1 #2
Workqueue: events flush_to_ldisc
[<c0014d58>] (unwind_backtrace+0x0/0xf8) from [<c0011908>] (show_stack+0x10/0x14)
[<c0011908>] (show_stack+0x10/0x14) from [<c035da34>] (dump_stack+0x6c/0xac)
[<c035da34>] (dump_stack+0x6c/0xac) from [<c01b581c>] (do_raw_spin_lock+0x100/0x17c)
[<c01b581c>] (do_raw_spin_lock+0x100/0x17c) from [<c03628a0>] (_raw_spin_lock_irqsave+0x20/0x28)
[<c03628a0>] (_raw_spin_lock_irqsave+0x20/0x28) from [<c0203224>] (uart_start+0x18/0x34)
[<c0203224>] (uart_start+0x18/0x34) from [<c01ef890>] (__receive_buf+0x4b4/0x738)
[<c01ef890>] (__receive_buf+0x4b4/0x738) from [<c01efb44>] (n_tty_receive_buf2+0x30/0x98)
[<c01efb44>] (n_tty_receive_buf2+0x30/0x98) from [<c01f2ba8>] (flush_to_ldisc+0xec/0x138)
[<c01f2ba8>] (flush_to_ldisc+0xec/0x138) from [<c0031af0>] (process_one_work+0xfc/0x348)
[<c0031af0>] (process_one_work+0xfc/0x348) from [<c0032138>] (worker_thread+0x138/0x37c)
[<c0032138>] (worker_thread+0x138/0x37c) from [<c0037a7c>] (kthread+0xa4/0xb0)
[<c0037a7c>] (kthread+0xa4/0xb0) from [<c000e5f8>] (ret_from_fork+0x14/0x3c)
-----

Release the port lock before calling tty_flip_buffer_push() and reacquire it
after the call.

Similar stuff was already done for few other drivers in the past, like:

commit 2389b27216
Author: Thomas Gleixner <tglx@linutronix.de>
Date:   Tue May 29 21:53:50 2007 +0100

    [ARM] 4417/1: Serial: Fix AMBA drivers locking

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-08-27 16:17:33 -07:00
..
8250 serial: 8250_dw: Report CTS asserted for auto flow 2013-08-19 17:12:21 -07:00
cpm_uart serial: use platform_{get,set}_drvdata() 2013-06-03 10:21:33 -07:00
jsm TTY: jsm, remove superfluous check 2013-03-18 16:17:20 -07:00
21285.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
68328serial.c Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu 2013-05-10 07:22:35 -07:00
altera_jtaguart.c tty: serial: altera_jtag: drop uart_port->lock before calling tty_flip_buffer_push() 2013-08-27 16:17:33 -07:00
altera_uart.c tty: serial: altera: drop uart_port->lock before calling tty_flip_buffer_push() 2013-08-27 16:17:33 -07:00
amba-pl010.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
amba-pl011.c serial: amba-pl011: Use __releases/__acquires annotations 2013-08-12 11:37:48 -07:00
apbuart.c tty: serial: apbuart: drop uart_port->lock before calling tty_flip_buffer_push() 2013-08-27 16:17:33 -07:00
apbuart.h
ar933x_uart.c tty: serial: ar933x: drop uart_port->lock before calling tty_flip_buffer_push() 2013-08-27 16:17:33 -07:00
arc_uart.c tty: serial: arc: drop uart_port->lock before calling tty_flip_buffer_push() 2013-08-27 16:17:33 -07:00
atmel_serial.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
bcm63xx_uart.c serial: remove unnecessary platform_set_drvdata() 2013-07-26 15:39:36 -07:00
bfin_sport_uart.c serial: bfin_sport_uart: Fix incorrect placement of __initdata 2013-08-12 11:37:47 -07:00
bfin_sport_uart.h
bfin_uart.c serial: bfin_uart: Fix incorrect placement of __initdata 2013-08-12 11:37:47 -07:00
clps711x.c serial: remove unnecessary platform_set_drvdata() 2013-07-26 15:39:36 -07:00
crisv10.c crisv10: use counts from tty_port 2013-03-18 16:26:33 -07:00
crisv10.h crisv10: use counts from tty_port 2013-03-18 16:26:33 -07:00
dz.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
dz.h
efm32-uart.c serial/efm32-uart: don't slur over failure in probe_dt 2013-07-31 18:05:41 -07:00
fsl_lpuart.c serial: fsl_lpuart: Return proper error on lpuart_serial_init error path 2013-07-26 16:01:20 -07:00
icom.c serial: icom: fix casting warning 2013-08-12 11:35:31 -07:00
icom.h
ifx6x60.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
ifx6x60.h serial:ifx6x60:Prevent data transfer when IFX6x60 port is shutdown 2012-11-01 08:50:01 -07:00
imx.c serial: i.MX: evaluate linux,stdout-path property 2013-08-12 11:23:53 -07:00
ioc3_serial.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
ioc4_serial.c serial: ioc4_serial: Staticize ioc4_serial_attach_one() 2013-08-12 11:35:32 -07:00
ip22zilog.c TTY: ip22zilog, fix tty_flip_buffer_push call 2013-01-16 07:36:47 -08:00
ip22zilog.h
Kconfig Merge 3.11-rc3 into tty-next 2013-07-29 12:32:30 -07:00
kgdb_nmi.c kgdb: remove #include <linux/serial_8250.h> from kgdb.h 2013-02-04 15:35:26 -08:00
kgdboc.c KGDB/KDB fixes and cleanups 2012-10-13 11:16:58 +09:00
lantiq.c serial: MIPS: lantiq: fix clock error check 2013-08-12 11:37:48 -07:00
lpc32xx_hs.c serial: lpc32xx: Fix fallout from tty_port conversion 2013-01-18 16:05:15 -08:00
m32r_sio_reg.h
m32r_sio.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
m32r_sio.h
Makefile serial:st-asc: Add ST ASC driver. 2013-07-26 16:08:02 -07:00
max310x.c serial: max310x: Fix dev_pm_ops 2013-07-29 12:47:37 -07:00
max3100.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
mcf.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
mfd.c Power management and ACPI updates for 3.11-rc1 2013-07-03 14:35:40 -07:00
mpc52xx_uart.c serial/mpc52xx_uart: fix kernel panic when system reboot 2013-06-17 12:49:43 -07:00
mpsc.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
mrst_max3110.c serial: mrst_max3110: fix casting warning 2013-08-12 11:35:31 -07:00
mrst_max3110.h
msm_serial_hs.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
msm_serial.c serial: msm_serial: fix comparison of different types 2013-08-12 11:35:32 -07:00
msm_serial.h msm_serial: Make baud_code detection more dynamic 2013-07-26 16:13:29 -07:00
msm_smd_tty.c TTY: msm_smd_tty, clean up activate/shutdown 2013-03-18 16:19:44 -07:00
mux.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
mxs-auart.c serial: mxs: remove the MXS_AUART_DMA_CONFIG 2013-08-05 15:05:17 +08:00
netx-serial.c serial: remove unnecessary platform_set_drvdata() 2013-07-26 15:39:36 -07:00
nwpserial.c tty: nwpserial: Pass correct pointer to free_irq() 2013-05-20 11:54:55 -07:00
of_serial.c serial: use platform_{get,set}_drvdata() 2013-06-03 10:21:33 -07:00
omap-serial.c Revert "OMAP: UART: Keep the TX fifo full when possible" 2013-08-27 16:02:18 -07:00
pch_uart.c serial: pch_uart: fix compilation warning 2013-08-14 18:33:43 -07:00
pmac_zilog.c serial: remove unnecessary platform_set_drvdata() 2013-07-26 15:39:36 -07:00
pmac_zilog.h
pnx8xxx_uart.c serial: remove unnecessary platform_set_drvdata() 2013-07-26 15:39:36 -07:00
pxa.c serial: pxa: Staticize local symbols 2013-08-12 11:10:16 -07:00
rp2.c serial: rp2: New driver for Comtrol RocketPort 2 cards 2013-01-17 17:28:39 -08:00
sa1100.c serial: remove unnecessary platform_set_drvdata() 2013-07-26 15:39:36 -07:00
samsung.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
samsung.h serial: samsung: fix casting warning 2013-08-12 11:35:31 -07:00
sb1250-duart.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
sc26xx.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
sccnxp.c Revert "serial: sccnxp: Add DT support" 2013-08-02 15:25:19 +08:00
serial_core.c serial: report base_baud after initialization 2013-07-26 16:03:05 -07:00
serial_ks8695.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
serial_txx9.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
serial-tegra.c serial: tegra: use NULL instead of 0 2013-08-12 11:35:32 -07:00
sh-sci.c serial: sh-sci: use dev_get_platdata() 2013-08-02 11:54:13 +08:00
sh-sci.h serial: sh-sci: remove obsolete Kconfig macros 2013-03-25 14:06:45 -07:00
sirfsoc_uart.c serial: sirf: add DMA support using dmaengine APIs 2013-08-19 17:13:22 -07:00
sirfsoc_uart.h serial: sirf: add DMA support using dmaengine APIs 2013-08-19 17:13:22 -07:00
sn_console.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
st-asc.c serial: st-asc: replace devm_request_and_ioremap by devm_ioremap_resource 2013-08-19 17:12:21 -07:00
suncore.c
sunhv.c serial: use platform_{get,set}_drvdata() 2013-06-03 10:21:33 -07:00
sunsab.c serial: use platform_{get,set}_drvdata() 2013-06-03 10:21:33 -07:00
sunsab.h
sunsu.c serial: use platform_{get,set}_drvdata() 2013-06-03 10:21:33 -07:00
sunzilog.c serial: use platform_{get,set}_drvdata() 2013-06-03 10:21:33 -07:00
sunzilog.h
timbuart.c serial: timbuart: Staticize local symbols 2013-08-12 11:35:31 -07:00
timbuart.h
uartlite.c tty: serial: uartlite: Support uartlite on big and little endian systems 2013-02-13 08:38:45 -08:00
ucc_uart.c driver: tty: add missing unregister in err case 2013-06-03 10:30:43 -07:00
vr41xx_siu.c serial: use dev_get_platdata() 2013-07-31 17:56:15 -07:00
vt8500_serial.c serial: remove unnecessary platform_set_drvdata() 2013-07-26 15:39:36 -07:00
xilinx_uartps.c ARM SoC specific changes 2013-07-02 13:43:38 -07:00
zs.c TTY: switch tty_flip_buffer_push 2013-01-15 22:30:15 -08:00
zs.h