serial: sirf: fix kernel panic caused by unpaired spinlock
commit
8b9ade9f74f8a279 coming from Viresh Kumar "tty: serial: sirfsoc: drop
uart_port->lock before calling tty_flip_buffer_push()" broke sirfsoc uart
driver by knic:
[ 5.129122] BUG: spinlock already unlocked on CPU#0, ip6tables/1331
[ 5.132554] lock: sirfsoc_uart_ports+0x4/0x8a0, .magic:
dead4ead,
.owner: <none>/-1, .owner_cpu: -1
[ 5.141651] CPU: 0 PID: 1331 Comm: ip6tables Tainted: G
W O 3.10.16 #3
[ 5.148866] [<
c0013528>] (unwind_backtrace+0x0/0xe0) from
[<
c0010e70>] (show_stack+0x10/0x14)
[ 5.157362] [<
c0010e70>] (show_stack+0x10/0x14) from
[<
c01a5e68>] (do_raw_spin_unlock+0x40/0xc8)
[ 5.166125] [<
c01a5e68>] (do_raw_spin_unlock+0x40/0xc8) from
[<
c03ff8b4>] (_raw_spin_unlock+0x8/0x40)
[ 5.175322] [<
c03ff8b4>] (_raw_spin_unlock+0x8/0x40) from
[<
c0203fcc>] (sirfsoc_uart_pio_rx_chars+0xa4/0xc0)
[ 5.185120] [<
c0203fcc>]
(sirfsoc_uart_pio_rx_chars+0xa4/0xc0) from [<
c0204fb8>]
(sirfsoc_rx_tmo_process_tl+0xdc/0x1e0)
[ 5.195875] [<
c0204fb8>]
(sirfsoc_rx_tmo_process_tl+0xdc/0x1e0) from [<
c0024b50>]
(tasklet_action+0x8c/0xec)
[ 5.205673] [<
c0024b50>] (tasklet_action+0x8c/0xec) from
[<
c00242a8>] (__do_softirq+0xec/0x1d4)
[ 5.214347] [<
c00242a8>] (__do_softirq+0xec/0x1d4) from
[<
c0024428>] (do_softirq+0x48/0x54)
[ 5.222674] [<
c0024428>] (do_softirq+0x48/0x54) from
[<
c0024690>] (irq_exit+0x74/0xc0)
[ 5.230573] [<
c0024690>] (irq_exit+0x74/0xc0) from
[<
c000e1e8>] (handle_IRQ+0x6c/0x90)
[ 5.238465] [<
c000e1e8>] (handle_IRQ+0x6c/0x90) from
[<
c000d500>] (__irq_svc+0x40/0x70)
[ 5.246446] [<
c000d500>] (__irq_svc+0x40/0x70) from
[<
c0092e7c>] (mark_page_accessed+0xc/0x68)
[ 5.255034] [<
c0092e7c>] (mark_page_accessed+0xc/0x68) from
[<
c00a2a4c>] (unmap_single_vma+0x3bc/0x550)
[ 5.264402] [<
c00a2a4c>] (unmap_single_vma+0x3bc/0x550) from
[<
c00a3b4c>] (unmap_vmas+0x44/0x54)
[ 5.273164] [<
c00a3b4c>] (unmap_vmas+0x44/0x54) from
[<
c00a81a8>] (exit_mmap+0xc4/0x1e0)
[ 5.281233] [<
c00a81a8>] (exit_mmap+0xc4/0x1e0) from
[<
c001bb78>] (mmput+0x3c/0xdc)
[ 5.288868] [<
c001bb78>] (mmput+0x3c/0xdc) from [<
c0021b0c>]
(do_exit+0x30c/0x828)
[ 5.296413] [<
c0021b0c>] (do_exit+0x30c/0x828) from
[<
c0022dac>] (do_group_exit+0x4c/0xb0)
[ 5.304653] [<
c0022dac>] (do_group_exit+0x4c/0xb0) from
[<
c0022e20>] (__wake_up_parent+0x0/0x18)
Root cause:
the commit dropped uart_port->lock before calling tty_flip_buffer_push(), but in sirfsoc-uart,
sirfsoc_uart_pio_rx_chars() can be called by sirfsoc_rx_tmo_process_tl(). here uart_port->lock
has not been taken yet. so that caused unpaired lock/unlock.
Solution:
This patch is doing a quick fix for that, it adds spin_lock/unlock(&port->lock) protect to
sirfsoc_uart_pio_rx_chars() in sirfsoc_rx_tmo_process_tl() to keep spin_lock/unlock in pair.
Signed-off-by: Qipan Li <Qipan.Li@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Cc: stable <stable@vger.kernel.org> # 3.12
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>