• Qipan Li's avatar
    serial: sirf: fix kernel panic caused by unpaired spinlock · fb78b811
    Qipan Li authored
    commit 8b9ade9f 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: default avatarQipan Li <Qipan.Li@csr.com>
    Signed-off-by: default avatarBarry Song <Baohua.Song@csr.com>
    Cc: stable <stable@vger.kernel.org> # 3.12
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    fb78b811
sirfsoc_uart.c 49.6 KB