From b311ef1d549bedf0459b9f6c0b9fd82587c20d70 Mon Sep 17 00:00:00 2001 From: Flynn xu Date: Wed, 27 Feb 2019 15:45:02 -0500 Subject: [PATCH] MLK-20989: Driver: lpuart: reset registers before enable lpuart Before calling devm_request_irq to register a sport->port.irq, the lpuart register might not be in a correct status. When LPUART Control register is not it's reset value, such as 0xbc0700, this indicate there are unhandled irqs, thus, irq handler lpuart32_int will be triggered right after devm_request_irq, and this happens before uart_add_one_port which would init sport->port.state, then lpuart32_int will call lpuart_txint, and lpuart_txint will access sport->port.state->xmit, but at this point, sport->port.state is not init yet, then, kernel panic. This can be reproduced with jailhouse support dual Linux on i.MX8. When the 2nd Linux is running, and echo a message repeatedly, the 1st Linux force the 2nd Linux to destroy without any notification to the 2nd Linux. Then boot the 2nd Linux again, the issue could be reproduced. Kernel dump: [ 0.795118] fsl-lpuart 5a060000.serial: failed to get alias id, errno -19 [ 0.801963] Unable to handle kernel NULL pointer dereference at virtual address 00000170 [ 0.809570] Mem abort info: [ 0.812241] Exception class = DABT (current EL), IL = 32 bits [ 0.817908] SET = 0, FnV = 0 [ 0.820829] EA = 0, S1PTW = 0 [ 0.823831] Data abort info: [ 0.826584] ISV = 0, ISS = 0x00000004 [ 0.830254] CM = 0, WnR = 0 [ 0.833090] [0000000000000170] user address but active_mm is swapper [ 0.839180] Internal error: Oops: 96000004 [#1] PREEMPT SMP [ 0.844516] Modules linked in: [ 0.847440] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.14.98-05833-gc561a05e6ee7 #209 [ 0.855024] Hardware name: Freescale i.MX8QXP MEK (DT) [ 0.859946] task: ffff800024000000 task.stack: ffff000008068000 [ 0.865628] PC is at lpuart_txint.isra.5+0x6c/0x388 [ 0.870288] LR is at lpuart_txint.isra.5+0x1c/0x388 [ 0.874957] pc : [] lr : [] pstate: 600001c5 [ 0.882045] sp : ffff000008003de0 [ 0.885212] x29: ffff000008003de0 x28: ffff800024000000 [ 0.890300] x27: 0000000000000000 x26: ffff0000092263e8 [ 0.895387] x25: ffff0000096d6c43 x24: ffff80002423a600 [ 0.900474] x23: 0000000000000009 x22: 00000000000001c0 [ 0.905562] x21: 0000000000000200 x20: 0000000000c00000 [ 0.910649] x19: ffff8000246bb018 x18: 0000000000000001 [ 0.915736] x17: 0000000000000001 x16: 0000000000000019 [ 0.920824] x15: ffffffffffffffff x14: ffffffffffffffff [ 0.925911] x13: 0000000000000038 x12: 0101010101010101 [ 0.930999] x11: 0000000000000020 x10: 0000000000000040 [ 0.936086] x9 : ffff000009552fe8 x8 : ffff800026000248 [ 0.941174] x7 : ffff800026000270 x6 : 0000000000000000 [ 0.946261] x5 : ffff800026000248 x4 : 0000000000000000 [ 0.951348] x3 : 00000000000001c0 x2 : 0000000000000000 [ 0.956436] x1 : 0000000000000003 x0 : 0000000000000000 [ 0.961526] Process swapper/0 (pid: 1, stack limit = 0xffff000008068000) [ 0.967947] Call trace: [ 0.970286] Exception stack(0xffff000008003ca0 to 0xffff000008003de0) [ 0.976461] 3ca0: 0000000000000000 0000000000000003 0000000000000000 00000000000001c0 [ 0.983962] 3cc0: 0000000000000000 ffff800026000248 0000000000000000 ffff800026000270 [ 0.991470] 3ce0: ffff800026000248 ffff000009552fe8 0000000000000040 0000000000000020 [ 0.998975] 3d00: 0101010101010101 0000000000000038 ffffffffffffffff ffffffffffffffff [ 1.006480] 3d20: 0000000000000019 0000000000000001 0000000000000001 ffff8000246bb018 [ 1.013986] 3d40: 0000000000c00000 0000000000000200 00000000000001c0 0000000000000009 [ 1.021493] 3d60: ffff80002423a600 ffff0000096d6c43 ffff0000092263e8 0000000000000000 [ 1.029001] 3d80: ffff800024000000 ffff000008003de0 ffff0000086398d4 ffff000008003de0 [ 1.036505] 3da0: ffff000008639924 00000000600001c5 ffff8000245eec00 ffff800024486000 [ 1.044013] 3dc0: 0000ffffffffffff ffff000009555e80 ffff000008003de0 ffff000008639924 [ 1.051520] [] lpuart_txint.isra.5+0x6c/0x388 [ 1.057188] [] lpuart32_int+0x2a8/0x680 [ 1.062363] [] __handle_irq_event_percpu+0x5c/0x148 [ 1.068530] [] handle_irq_event_percpu+0x1c/0x58 [ 1.074451] [] handle_irq_event+0x48/0x78 [ 1.079792] [] handle_fasteoi_irq+0xa8/0x180 [ 1.085379] [] generic_handle_irq+0x24/0x38 [ 1.090881] [] __handle_domain_irq+0x5c/0xb8 [ 1.096469] [] gic_handle_irq+0x78/0x174 [ 1.101722] Exception stack(0xffff00000806b980 to 0xffff00000806bac0) [ 1.107895] b980: ffff80002423a6a4 0000000000000000 0000000000000005 0000000000000000 [ 1.115400] b9a0: 0000000000000004 0000000000000003 000000000000003f 0000000000000000 [ 1.122909] b9c0: ffff80002444de80 0000000000000000 0000000000000040 0000000000000020 [ 1.130413] b9e0: 0101010101010101 0000000000000038 ffffffffffffffff ffffffffffffffff [ 1.137920] ba00: 0000000000000019 0000000000000001 0000000000000001 ffff80002423a600 [ 1.145425] ba20: ffff80002444de00 0000000000000009 ffff80002423a628 0000000000000000 [ 1.152931] ba40: ffff80002423a758 ffff80002423a6a4 0000000000000000 0000000000000000 [ 1.160437] ba60: ffff00000951aae8 ffff00000806bac0 ffff00000811dcb4 ffff00000806bac0 [ 1.167943] ba80: ffff000008dd6ff0 0000000040000005 ffff00000806bad0 ffff00000811dec8 [ 1.175451] baa0: ffffffffffffffff ffff80002444de00 ffff00000806bac0 ffff000008dd6ff0 [ 1.182956] [] el1_irq+0xb0/0x124 [ 1.187629] [] _raw_spin_unlock_irqrestore+0x18/0x48 [ 1.193882] [] __setup_irq+0x524/0x7c8 [ 1.198968] [] request_threaded_irq+0xe4/0x1a0 [ 1.204722] [] devm_request_threaded_irq+0x7c/0xf8 [ 1.210811] [] lpuart_probe+0x364/0x580 [ 1.215984] [] platform_drv_probe+0x58/0xb8 [ 1.221489] [] driver_probe_device+0x210/0x2d0 [ 1.227240] [] __driver_attach+0xbc/0xc0 [ 1.232497] [] bus_for_each_dev+0x4c/0x98 [ 1.237834] [] driver_attach+0x20/0x28 [ 1.242919] [] bus_add_driver+0x1b8/0x228 [ 1.248255] [] driver_register+0x60/0xf8 [ 1.253510] [] __platform_driver_register+0x40/0x48 [ 1.259687] [] lpuart_serial_init+0x38/0x5c [ 1.265189] [] do_one_initcall+0x38/0x128 [ 1.270527] [] kernel_init_freeable+0x188/0x22c [ 1.276366] [] kernel_init+0x10/0x108 [ 1.281368] [] ret_from_fork+0x10/0x18 [ 1.286458] Code: 14000022 910802b5 39428a61 71000c3f (296e0aa3) [ 1.292305] ---[ end trace 3559accd3c908fe3 ]--- [ 1.296713] Kernel panic - not syncing: Fatal exception in interrupt [ 1.302798] SMP: stopping secondary CPUs [ 1.306557] Kernel Offset: disabled [ 1.309889] CPU features: 0x0802008 [ 1.313223] Memory Limit: none [ 1.316146] ---[ end Kernel panic - not syncing: Fatal exception in interrupt Suggested-by: Peng Fan Signed-off-by: Flynn xu Acked-by: Fugang Duan --- drivers/tty/serial/fsl_lpuart.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 421b0eb5f3e6de..4026613122fe05 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2468,6 +2468,12 @@ static int lpuart_probe(struct platform_device *pdev) platform_set_drvdata(pdev, &sport->port); + /* reset lpuart registers before enable */ + if (lpuart_is_32(sport)) + lpuart32_shutdown(&sport->port); + else + lpuart_shutdown(&sport->port); + if (lpuart_is_32(sport)) { lpuart_reg.cons = LPUART32_CONSOLE; ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart32_int, 0,