* TDA998x crash on HDLCD probe failure
@ 2016-11-24 13:18 Robin Murphy
2016-11-24 13:29 ` Russell King - ARM Linux
0 siblings, 1 reply; 5+ messages in thread
From: Robin Murphy @ 2016-11-24 13:18 UTC (permalink / raw)
To: linux-arm-kernel
Hi Liviu, Russell,
I'd been meaning to try digging into this if it hadn't gone away since I
first noticed it, but I don't really have the time and it still happens
with 4.9-rc and today's -next. Representative splat below, but in
summary what happens is that if the HDLCD fails to probe, the TDA998x
connector seems to get cleaned up twice, resulting in a NULL dereference
the second time. I got as far as sketching out the following flow from a
debug session (on the same 4.8-rc2 kernel), but I don't know nearly
enough to tell which driver is at fault:
hdlcd_drm_bind
-> drm_fbdev_cma_init (fails)
...
-> drm_mode_config_cleanup
...
-> drm_connector_cleanup
-> component_unbind_all
...
-> tda998x_unbind
-> drm_connector_cleanup (NULL connector)
It's easily reproduced on Juno by booting arm64 defconfig with
CONFIG_CMA_SIZE_MBYTES=1 and a sufficiently large monitor connected to
warrant a >1MB framebuffer.
Robin.
[ 4.107349] hdlcd 7ff60000.hdlcd: failed to allocate buffer with size
7680000
[ 4.114459] hdlcd 7ff60000.hdlcd: Failed to set initial hw configuration.
[ 4.121888] Unable to handle kernel NULL pointer dereference at
virtual address 00000000
[ 4.129951] pgd = ffffff80091e0000
[ 4.133345] [00000000] *pgd=00000009ffffe003, *pud=00000009ffffe003,
*pmd=0000000000000000
[ 4.141613] Internal error: Oops: 96000005 [#1] PREEMPT SMP
[ 4.147144] Modules linked in:
[ 4.150188] CPU: 0 PID: 122 Comm: kworker/u12:2 Not tainted
4.8.0-rc2+ #989
[ 4.157097] Hardware name: ARM Juno development board (r1) (DT)
[ 4.162981] Workqueue: deferwq deferred_probe_work_func
[ 4.168173] task: ffffffc975d93200 task.stack: ffffffc975dac000
[ 4.174055] PC is at drm_connector_cleanup+0x58/0x1c0
[ 4.179074] LR is at tda998x_unbind+0x24/0x40
[ 4.183401] pc : [<ffffff80084c46f0>] lr : [<ffffff800850414c>]
pstate: 00000045
[ 4.190750] sp : ffffffc975dafa10
[ 4.194041] x29: ffffffc975dafa10 x28: ffffffc9768152a8
[ 4.199325] x27: ffffffc97ff46450 x26: ffffff8008d99000
[ 4.204608] x25: dead000000000100 x24: dead000000000200
[ 4.209891] x23: ffffffc976bf91e8 x22: 0000000000000000
[ 4.215172] x21: ffffffc976bf9170 x20: ffffffc976bf9170
[ 4.220454] x19: ffffffc976bf9018 x18: 0000000000000000
[ 4.225737] x17: 0000000074ce71ee x16: 000000008ff5d35f
[ 4.231019] x15: ffffffc97681e91c x14: ffffffffffffffff
[ 4.236301] x13: ffffffc97681e185 x12: 0000000000000038
[ 4.241583] x11: 0101010101010101 x10: 0000000000000000
[ 4.246866] x9 : 0000000040000000 x8 : 0000000000210d00
[ 4.252148] x7 : ffffffc97fea8c00 x6 : 000000000000001b
[ 4.257430] x5 : ffffff80084b7b8c x4 : 0000000000000080
[ 4.262712] x3 : ffffff8008504128 x2 : ffffffc975df3800
[ 4.267993] x1 : 0000000000000000 x0 : 0000000000000000
[ 4.273274]
[ 4.274759] Process kworker/u12:2 (pid: 122, stack limit =
0xffffffc975dac020)
[ 4.281938] Stack: (0xffffffc975dafa10 to 0xffffffc975db0000)
[ 4.285576] ata1: SATA link up 3.0 Gbps (SStatus 123 SControl 0)
[ 4.293602] fa00: ffffffc975dafa60
ffffff800850414c
[ 4.301386] fa20: ffffffc976bf9018 ffffffc976bf9170 0000000000000000
ffffffc975df3800
[ 4.309170] fa40: ffffffc975c1e1a0 ffffffc976b14400 ffffffc976b14410
ffffff8008518784
[ 4.316954] fa60: ffffffc975dafa80 ffffff8008507918 ffffffc976bdf080
ffffffffffffffd8
[ 4.324737] fa80: ffffffc975dafaa0 ffffff8008507a0c ffffffc975c1e180
ffffffc976b14400
[ 4.332521] faa0: ffffffc975dafae0 ffffff80084d5adc ffffffc975df3800
fffffffffffffff4
[ 4.340305] fac0: ffffffc976b14410 ffffffc975df3018 ffffffc975df3018
ffffff80084d5ab4
[ 4.348089] fae0: ffffffc975dafb30 ffffff8008507b58 ffffffc976bdf080
0000000000000028
[ 4.355873] fb00: ffffff8008d3d600 0000000000000001 ffffffc975c1e180
ffffffc976bdf080
[ 4.363657] fb20: ffffffc975c1e098 ffffff80084d5428 ffffffc975dafb90
ffffff8008507c50
[ 4.371441] fb40: ffffffc975c1e180 ffffff8008d3d5f0 ffffffc976bdf080
ffffffc976b57000
[ 4.379225] fb60: ffffff8008d3d000 ffffffc976815000 ffffff8008d926c6
ffffffc976815020
[ 4.387009] fb80: ffffffc976815078 ffffffc9768152a8 ffffffc975dafbd0
ffffff8008504b90
[ 4.394793] fba0: ffffff8008d3d4e8 ffffffc976b57020 ffffffc976b57004
ffffffc976b57000
[ 4.402577] fbc0: ffffff8008504b78 ffffff80086bf8cc ffffffc975dafbe0
ffffff80086bf914
[ 4.410360] fbe0: ffffffc975dafc20 ffffff800850d094 ffffffc976b57020
ffffff8008dc4000
[ 4.418144] fc00: 0000000000000000 ffffff8008d3d448 0000000000000004
ffffff8008dc4000
[ 4.425928] fc20: ffffffc975dafc60 ffffff800850d28c ffffff8008d3d448
ffffffc975dafd00
[ 4.433711] fc40: ffffffc976b57020 0000000000000001 ffffffc975e3b400
ffffff800850b114
[ 4.441495] fc60: ffffffc975dafc90 ffffff800850b108 0000000000000000
ffffffc975dafd00
[ 4.449279] fc80: ffffff800850d1f0 0000000000000001 ffffffc975dafcd0
ffffff800850cd64
[ 4.457062] fca0: ffffffc976b57020 ffffffc976b57080 ffffff8008d584f0
ffffffc976b57080
[ 4.464846] fcc0: ffffffc976af38d0 ffffffc975c20168 ffffffc975dafd10
ffffff800850d338
[ 4.472630] fce0: ffffffc976b57020 ffffffc976b57020 ffffff8008d584f0
ffffff8008d3d000
[ 4.480414] fd00: ffffffc976b57020 0000000000000001 ffffffc975dafd20
ffffff800850c124
[ 4.488198] fd20: ffffffc975dafd50 ffffff800850c5b0 ffffffc976b57020
ffffff8008d3d848
[ 4.495982] fd40: ffffff8008d3d820 ffffff800850c5a8 ffffffc975dafd80
ffffff80080d2998
[ 4.503765] fd60: 0000000000000000 ffffffc976bd4500 ffffff8008d3d880
0000000000000000
[ 4.511549] fd80: ffffffc975dafdc0 ffffff80080d2c40 ffffffc976bd4500
ffffffc976815000
[ 4.519333] fda0: ffffffc976bd4530 ffffffc976815020 ffffff8008ce5000
ffffffc975dac000
[ 4.527117] fdc0: ffffffc975dafe20 ffffff80080d8918 ffffffc976bd3880
ffffff8008d9cb08
[ 4.534900] fde0: ffffff8008ace5f0 ffffffc976bd4500 ffffff80080d2bf8
0000000000000000
[ 4.542683] fe00: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 4.550467] fe20: 0000000000000000 ffffff8008082e90 ffffff80080d8848
ffffffc976bd3880
[ 4.558250] fe40: 0000000000000000 0000000000000000 0000000000000000
0000d00420000400
[ 4.566034] fe60: ffffffc975dafea0 0000000000000000 ffffff80080d8848
ffffffc976bd4500
[ 4.573817] fe80: 0000000000000000 0000000000000000 ffffffc975dafe90
ffffffc975dafe90
[ 4.581602] fea0: 0000000000000000 ffffff8000000000 ffffffc975dafeb0
ffffffc975dafeb0
[ 4.589384] fec0: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 4.597168] fee0: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 4.604951] ff00: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 4.612734] ff20: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 4.620517] ff40: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 4.628299] ff60: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 4.636082] ff80: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 4.643865] ffa0: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 4.651648] ffc0: 0000000000000000 0000000000000005 0000000000000000
0000000000000000
[ 4.659431] ffe0: 0000000000000000 0000000000000000 100a0c0062800800
42200c0000000c00
[ 4.667210] Call trace:
[ 4.669643] Exception stack(0xffffffc975daf840 to 0xffffffc975daf970)
[ 4.676040] f840: ffffffc976bf9018 0000008000000000 ffffffc975dafa10
ffffff80084c46f0
[ 4.683823] f860: 0000000000000000 0000000000000000 00000001800f000e
0000000000000001
[ 4.691607] f880: ffffffc9769ef2a0 00000001000f000f ffffffbf25da7a00
ffffffc976803100
[ 4.699390] f8a0: ffffffc975daf9b0 ffffff80081a899c ffffffc976803100
ffffff80083446b4
[ 4.707174] f8c0: ffffffbf25da7a00 ffffffc975dac000 ffffffc9769ef2a0
000000000003c380
[ 4.714958] f8e0: 0000000000000000 0000000000000000 ffffffc975df3800
ffffff8008504128
[ 4.722741] f900: 0000000000000080 ffffff80084b7b8c 000000000000001b
ffffffc97fea8c00
[ 4.730524] f920: 0000000000210d00 0000000040000000 0000000000000000
0101010101010101
[ 4.738308] f940: 0000000000000038 ffffffc97681e185 ffffffffffffffff
ffffffc97681e91c
[ 4.746090] f960: 000000008ff5d35f 0000000074ce71ee
[ 4.750937] [<ffffff80084c46f0>] drm_connector_cleanup+0x58/0x1c0
[ 4.756990] [<ffffff800850414c>] tda998x_unbind+0x24/0x40
[ 4.762354] [<ffffff8008507918>] component_unbind.isra.4+0x28/0x50
[ 4.768492] [<ffffff8008507a0c>] component_unbind_all+0xcc/0xd8
[ 4.774373] [<ffffff80084d5adc>] hdlcd_drm_bind+0x234/0x418
[ 4.779909] [<ffffff8008507b58>] try_to_bring_up_master+0x140/0x1a0
[ 4.786133] [<ffffff8008507c50>] component_add+0x98/0x170
[ 4.791496] [<ffffff8008504b90>] tda998x_probe+0x18/0x20
[ 4.796774] [<ffffff80086bf914>] i2c_device_probe+0x164/0x258
[ 4.802481] [<ffffff800850d094>] driver_probe_device+0x204/0x2b0
[ 4.808447] [<ffffff800850d28c>] __device_attach_driver+0x9c/0xf8
[ 4.814498] [<ffffff800850b108>] bus_for_each_drv+0x58/0x98
[ 4.820033] [<ffffff800850cd64>] __device_attach+0xc4/0x138
[ 4.825567] [<ffffff800850d338>] device_initial_probe+0x10/0x18
[ 4.831446] [<ffffff800850c124>] bus_probe_device+0x94/0xa0
[ 4.836981] [<ffffff800850c5b0>] deferred_probe_work_func+0x78/0xb0
[ 4.843207] [<ffffff80080d2998>] process_one_work+0x118/0x378
[ 4.848914] [<ffffff80080d2c40>] worker_thread+0x48/0x498
[ 4.854276] [<ffffff80080d8918>] kthread+0xd0/0xe8
[ 4.859036] [<ffffff8008082e90>] ret_from_fork+0x10/0x40
[ 4.864314] Code: f2fbd5b9 f2fbd5b8 f8478ee0 eb17001f (f9400013)
[ 4.870472] ---[ end trace a643cfe4ce1d838b ]---
^ permalink raw reply [flat|nested] 5+ messages in thread* TDA998x crash on HDLCD probe failure 2016-11-24 13:18 TDA998x crash on HDLCD probe failure Robin Murphy @ 2016-11-24 13:29 ` Russell King - ARM Linux 2016-11-24 13:49 ` Robin Murphy 0 siblings, 1 reply; 5+ messages in thread From: Russell King - ARM Linux @ 2016-11-24 13:29 UTC (permalink / raw) To: linux-arm-kernel On Thu, Nov 24, 2016 at 01:18:39PM +0000, Robin Murphy wrote: > Hi Liviu, Russell, > > I'd been meaning to try digging into this if it hadn't gone away since I > first noticed it, but I don't really have the time and it still happens > with 4.9-rc and today's -next. Representative splat below, but in > summary what happens is that if the HDLCD fails to probe, the TDA998x > connector seems to get cleaned up twice, resulting in a NULL dereference > the second time. I got as far as sketching out the following flow from a > debug session (on the same 4.8-rc2 kernel), but I don't know nearly > enough to tell which driver is at fault: > > hdlcd_drm_bind > -> drm_fbdev_cma_init (fails) > ... > -> drm_mode_config_cleanup > ... > -> drm_connector_cleanup > -> component_unbind_all > ... > -> tda998x_unbind > -> drm_connector_cleanup (NULL connector) > > It's easily reproduced on Juno by booting arm64 defconfig with > CONFIG_CMA_SIZE_MBYTES=1 and a sufficiently large monitor connected to > warrant a >1MB framebuffer. It looks to me like a hdlcd bug. The probe path operates in this order: - allocates hdlcd - 1 - allocates drm device - 2 - drm_mode_config_init - 3 - hdlcd_load - 4 - binds all components - 5 - enables runtime PM - 6 - drm_vblank_init - 7 - drm_mode_config_reset - 8 - drm_kms_helper_poll_init - 9 - drm_fbdev_cma_init - 10 - drm_dev_register - 11 However, the cleanup operates in this order: - drm_fbdev_cma_fini - undoes 10 - drm_kms_helper_poll_fini - undoes 9 - drm_mode_config_cleanup - undoes 3 - drm_vblank_cleanup - undoes 7 - pm_runtime_disable - undoes 6 - component_unbind_all - undoes 5 - drm_irq_uninstall - undoes 4 - of_reserved_mem_device_release - undoes other half of 4 - drm_dev_unref - undoes 2 Spot the step which is out of the correct order - drm_mode_config_cleanup() is misplaced - it's reversing the actions of drm_mode_config_init(), not drm_mode_config_reset(). So, drm_mode_config_cleanup() should be much later, after step 4 has been undone, otherwise there are paths that leave various DRM objects (created by drm_mode_create_standard_properties()) referenced, and will cause problems exactly like you're seeing here. -- RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up according to speedtest.net. ^ permalink raw reply [flat|nested] 5+ messages in thread
* TDA998x crash on HDLCD probe failure 2016-11-24 13:29 ` Russell King - ARM Linux @ 2016-11-24 13:49 ` Robin Murphy 2016-11-24 14:40 ` Robin Murphy 0 siblings, 1 reply; 5+ messages in thread From: Robin Murphy @ 2016-11-24 13:49 UTC (permalink / raw) To: linux-arm-kernel On 24/11/16 13:29, Russell King - ARM Linux wrote: > On Thu, Nov 24, 2016 at 01:18:39PM +0000, Robin Murphy wrote: >> Hi Liviu, Russell, >> >> I'd been meaning to try digging into this if it hadn't gone away since I >> first noticed it, but I don't really have the time and it still happens >> with 4.9-rc and today's -next. Representative splat below, but in >> summary what happens is that if the HDLCD fails to probe, the TDA998x >> connector seems to get cleaned up twice, resulting in a NULL dereference >> the second time. I got as far as sketching out the following flow from a >> debug session (on the same 4.8-rc2 kernel), but I don't know nearly >> enough to tell which driver is at fault: >> >> hdlcd_drm_bind >> -> drm_fbdev_cma_init (fails) >> ... >> -> drm_mode_config_cleanup >> ... >> -> drm_connector_cleanup >> -> component_unbind_all >> ... >> -> tda998x_unbind >> -> drm_connector_cleanup (NULL connector) >> >> It's easily reproduced on Juno by booting arm64 defconfig with >> CONFIG_CMA_SIZE_MBYTES=1 and a sufficiently large monitor connected to >> warrant a >1MB framebuffer. > > It looks to me like a hdlcd bug. > > The probe path operates in this order: > > - allocates hdlcd - 1 > - allocates drm device - 2 > - drm_mode_config_init - 3 > - hdlcd_load - 4 > - binds all components - 5 > - enables runtime PM - 6 > - drm_vblank_init - 7 > - drm_mode_config_reset - 8 > - drm_kms_helper_poll_init - 9 > - drm_fbdev_cma_init - 10 > - drm_dev_register - 11 > > However, the cleanup operates in this order: > - drm_fbdev_cma_fini - undoes 10 > - drm_kms_helper_poll_fini - undoes 9 > - drm_mode_config_cleanup - undoes 3 > - drm_vblank_cleanup - undoes 7 > - pm_runtime_disable - undoes 6 > - component_unbind_all - undoes 5 > - drm_irq_uninstall - undoes 4 > - of_reserved_mem_device_release - undoes other half of 4 > - drm_dev_unref - undoes 2 > > Spot the step which is out of the correct order - drm_mode_config_cleanup() > is misplaced - it's reversing the actions of drm_mode_config_init(), not > drm_mode_config_reset(). Thanks for the explanation - that saves at least a day's worth of me trying to understand DRM code :) > So, drm_mode_config_cleanup() should be much later, after step 4 has > been undone, otherwise there are paths that leave various DRM objects > (created by drm_mode_create_standard_properties()) referenced, and > will cause problems exactly like you're seeing here. Liviu, can I leave this with you then? Robin. ^ permalink raw reply [flat|nested] 5+ messages in thread
* TDA998x crash on HDLCD probe failure 2016-11-24 13:49 ` Robin Murphy @ 2016-11-24 14:40 ` Robin Murphy 2016-11-24 14:51 ` Liviu Dudau 0 siblings, 1 reply; 5+ messages in thread From: Robin Murphy @ 2016-11-24 14:40 UTC (permalink / raw) To: linux-arm-kernel On 24/11/16 13:49, Robin Murphy wrote: > On 24/11/16 13:29, Russell King - ARM Linux wrote: >> On Thu, Nov 24, 2016 at 01:18:39PM +0000, Robin Murphy wrote: >>> Hi Liviu, Russell, >>> >>> I'd been meaning to try digging into this if it hadn't gone away since I >>> first noticed it, but I don't really have the time and it still happens >>> with 4.9-rc and today's -next. Representative splat below, but in >>> summary what happens is that if the HDLCD fails to probe, the TDA998x >>> connector seems to get cleaned up twice, resulting in a NULL dereference >>> the second time. I got as far as sketching out the following flow from a >>> debug session (on the same 4.8-rc2 kernel), but I don't know nearly >>> enough to tell which driver is at fault: >>> >>> hdlcd_drm_bind >>> -> drm_fbdev_cma_init (fails) >>> ... >>> -> drm_mode_config_cleanup >>> ... >>> -> drm_connector_cleanup >>> -> component_unbind_all >>> ... >>> -> tda998x_unbind >>> -> drm_connector_cleanup (NULL connector) >>> >>> It's easily reproduced on Juno by booting arm64 defconfig with >>> CONFIG_CMA_SIZE_MBYTES=1 and a sufficiently large monitor connected to >>> warrant a >1MB framebuffer. >> >> It looks to me like a hdlcd bug. >> >> The probe path operates in this order: >> >> - allocates hdlcd - 1 >> - allocates drm device - 2 >> - drm_mode_config_init - 3 >> - hdlcd_load - 4 >> - binds all components - 5 >> - enables runtime PM - 6 >> - drm_vblank_init - 7 >> - drm_mode_config_reset - 8 >> - drm_kms_helper_poll_init - 9 >> - drm_fbdev_cma_init - 10 >> - drm_dev_register - 11 >> >> However, the cleanup operates in this order: >> - drm_fbdev_cma_fini - undoes 10 >> - drm_kms_helper_poll_fini - undoes 9 >> - drm_mode_config_cleanup - undoes 3 >> - drm_vblank_cleanup - undoes 7 >> - pm_runtime_disable - undoes 6 >> - component_unbind_all - undoes 5 >> - drm_irq_uninstall - undoes 4 >> - of_reserved_mem_device_release - undoes other half of 4 >> - drm_dev_unref - undoes 2 >> >> Spot the step which is out of the correct order - drm_mode_config_cleanup() >> is misplaced - it's reversing the actions of drm_mode_config_init(), not >> drm_mode_config_reset(). > > Thanks for the explanation - that saves at least a day's worth of me > trying to understand DRM code :) > >> So, drm_mode_config_cleanup() should be much later, after step 4 has >> been undone, otherwise there are paths that leave various DRM objects >> (created by drm_mode_create_standard_properties()) referenced, and >> will cause problems exactly like you're seeing here. > > Liviu, can I leave this with you then? That said, I just tried the quick and obvious thing over lunch and it does *seem* to be OK: ----->8----- From: Robin Murphy <robin.murphy@arm.com> Subject: [PATCH] drm: hdlcd: Fix cleanup order If hdlcd_drm_bind() fails at drm_fbdev_cma_init(), its cleanup will call drm_mode_config_cleanup() as if to balance drm_mode_config_reset(). The net result is that drm_connector_cleanup() will clean up the active connectors long before component_unbind_all() gets called, so when the connector later tries to clean up itself after being unbound, Bad Things can happen: [ 4.121888] Unable to handle kernel NULL pointer dereference at virtual address 00000000 [ 4.129951] pgd = ffffff80091e0000 [ 4.133345] [00000000] *pgd=00000009ffffe003, *pud=00000009ffffe003, *pmd=0000000000000000 [ 4.141613] Internal error: Oops: 96000005 [#1] PREEMPT SMP [ 4.147144] Modules linked in: [ 4.150188] CPU: 0 PID: 122 Comm: kworker/u12:2 Not tainted 4.8.0-rc2+ #989 [ 4.157097] Hardware name: ARM Juno development board (r1) (DT) [ 4.162981] Workqueue: deferwq deferred_probe_work_func [ 4.168173] task: ffffffc975d93200 task.stack: ffffffc975dac000 [ 4.174055] PC is at drm_connector_cleanup+0x58/0x1c0 [ 4.179074] LR is at tda998x_unbind+0x24/0x40 [ 4.183401] pc : [<ffffff80084c46f0>] lr : [<ffffff800850414c>] pstate: 00000045 [ 4.190750] sp : ffffffc975dafa10 [ 4.194041] x29: ffffffc975dafa10 x28: ffffffc9768152a8 [ 4.199325] x27: ffffffc97ff46450 x26: ffffff8008d99000 [ 4.204608] x25: dead000000000100 x24: dead000000000200 [ 4.209891] x23: ffffffc976bf91e8 x22: 0000000000000000 [ 4.215172] x21: ffffffc976bf9170 x20: ffffffc976bf9170 [ 4.220454] x19: ffffffc976bf9018 x18: 0000000000000000 [ 4.225737] x17: 0000000074ce71ee x16: 000000008ff5d35f [ 4.231019] x15: ffffffc97681e91c x14: ffffffffffffffff [ 4.236301] x13: ffffffc97681e185 x12: 0000000000000038 [ 4.241583] x11: 0101010101010101 x10: 0000000000000000 [ 4.246866] x9 : 0000000040000000 x8 : 0000000000210d00 [ 4.252148] x7 : ffffffc97fea8c00 x6 : 000000000000001b [ 4.257430] x5 : ffffff80084b7b8c x4 : 0000000000000080 [ 4.262712] x3 : ffffff8008504128 x2 : ffffffc975df3800 [ 4.267993] x1 : 0000000000000000 x0 : 0000000000000000 ... [ 4.750937] [<ffffff80084c46f0>] drm_connector_cleanup+0x58/0x1c0 [ 4.756990] [<ffffff800850414c>] tda998x_unbind+0x24/0x40 [ 4.762354] [<ffffff8008507918>] component_unbind.isra.4+0x28/0x50 [ 4.768492] [<ffffff8008507a0c>] component_unbind_all+0xcc/0xd8 [ 4.774373] [<ffffff80084d5adc>] hdlcd_drm_bind+0x234/0x418 [ 4.779909] [<ffffff8008507b58>] try_to_bring_up_master+0x140/0x1a0 [ 4.786133] [<ffffff8008507c50>] component_add+0x98/0x170 [ 4.791496] [<ffffff8008504b90>] tda998x_probe+0x18/0x20 [ 4.796774] [<ffffff80086bf914>] i2c_device_probe+0x164/0x258 [ 4.802481] [<ffffff800850d094>] driver_probe_device+0x204/0x2b0 [ 4.808447] [<ffffff800850d28c>] __device_attach_driver+0x9c/0xf8 [ 4.814498] [<ffffff800850b108>] bus_for_each_drv+0x58/0x98 [ 4.820033] [<ffffff800850cd64>] __device_attach+0xc4/0x138 [ 4.825567] [<ffffff800850d338>] device_initial_probe+0x10/0x18 [ 4.831446] [<ffffff800850c124>] bus_probe_device+0x94/0xa0 [ 4.836981] [<ffffff800850c5b0>] deferred_probe_work_func+0x78/0xb0 [ 4.843207] [<ffffff80080d2998>] process_one_work+0x118/0x378 [ 4.848914] [<ffffff80080d2c40>] worker_thread+0x48/0x498 [ 4.854276] [<ffffff80080d8918>] kthread+0xd0/0xe8 [ 4.859036] [<ffffff8008082e90>] ret_from_fork+0x10/0x40 [ 4.864314] Code: f2fbd5b9 f2fbd5b8 f8478ee0 eb17001f (f9400013) [ 4.870472] ---[ end trace a643cfe4ce1d838b ]--- Fix this by moving the drm_mode_config_cleanup() much later such that it correctly balances drm_mode_config_init(). Suggested-by: Russell King <linux@armlinux.org.uk> Signed-off-by: Robin Murphy <robin.murphy@arm.com> --- drivers/gpu/drm/arm/hdlcd_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index 59b76054edc9..1a4fff7c0a7c 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -420,7 +420,6 @@ static int hdlcd_drm_bind(struct device *dev) err_fbdev: drm_kms_helper_poll_fini(drm); - drm_mode_config_cleanup(drm); drm_vblank_cleanup(drm); err_vblank: pm_runtime_disable(drm->dev); @@ -432,6 +431,7 @@ static int hdlcd_drm_bind(struct device *dev) drm_irq_uninstall(drm); of_reserved_mem_device_release(drm->dev); err_free: + drm_mode_config_cleanup(drm); dev_set_drvdata(dev, NULL); drm_dev_unref(drm); -- 2.10.2.dirty ^ permalink raw reply related [flat|nested] 5+ messages in thread
* TDA998x crash on HDLCD probe failure 2016-11-24 14:40 ` Robin Murphy @ 2016-11-24 14:51 ` Liviu Dudau 0 siblings, 0 replies; 5+ messages in thread From: Liviu Dudau @ 2016-11-24 14:51 UTC (permalink / raw) To: linux-arm-kernel On Thu, Nov 24, 2016 at 02:40:50PM +0000, Robin Murphy wrote: > On 24/11/16 13:49, Robin Murphy wrote: > > On 24/11/16 13:29, Russell King - ARM Linux wrote: > >> On Thu, Nov 24, 2016 at 01:18:39PM +0000, Robin Murphy wrote: > >>> Hi Liviu, Russell, > >>> > >>> I'd been meaning to try digging into this if it hadn't gone away since I > >>> first noticed it, but I don't really have the time and it still happens > >>> with 4.9-rc and today's -next. Representative splat below, but in > >>> summary what happens is that if the HDLCD fails to probe, the TDA998x > >>> connector seems to get cleaned up twice, resulting in a NULL dereference > >>> the second time. I got as far as sketching out the following flow from a > >>> debug session (on the same 4.8-rc2 kernel), but I don't know nearly > >>> enough to tell which driver is at fault: > >>> > >>> hdlcd_drm_bind > >>> -> drm_fbdev_cma_init (fails) > >>> ... > >>> -> drm_mode_config_cleanup > >>> ... > >>> -> drm_connector_cleanup > >>> -> component_unbind_all > >>> ... > >>> -> tda998x_unbind > >>> -> drm_connector_cleanup (NULL connector) > >>> > >>> It's easily reproduced on Juno by booting arm64 defconfig with > >>> CONFIG_CMA_SIZE_MBYTES=1 and a sufficiently large monitor connected to > >>> warrant a >1MB framebuffer. > >> > >> It looks to me like a hdlcd bug. > >> > >> The probe path operates in this order: > >> > >> - allocates hdlcd - 1 > >> - allocates drm device - 2 > >> - drm_mode_config_init - 3 > >> - hdlcd_load - 4 > >> - binds all components - 5 > >> - enables runtime PM - 6 > >> - drm_vblank_init - 7 > >> - drm_mode_config_reset - 8 > >> - drm_kms_helper_poll_init - 9 > >> - drm_fbdev_cma_init - 10 > >> - drm_dev_register - 11 > >> > >> However, the cleanup operates in this order: > >> - drm_fbdev_cma_fini - undoes 10 > >> - drm_kms_helper_poll_fini - undoes 9 > >> - drm_mode_config_cleanup - undoes 3 > >> - drm_vblank_cleanup - undoes 7 > >> - pm_runtime_disable - undoes 6 > >> - component_unbind_all - undoes 5 > >> - drm_irq_uninstall - undoes 4 > >> - of_reserved_mem_device_release - undoes other half of 4 > >> - drm_dev_unref - undoes 2 > >> > >> Spot the step which is out of the correct order - drm_mode_config_cleanup() > >> is misplaced - it's reversing the actions of drm_mode_config_init(), not > >> drm_mode_config_reset(). > > > > Thanks for the explanation - that saves at least a day's worth of me > > trying to understand DRM code :) > > > >> So, drm_mode_config_cleanup() should be much later, after step 4 has > >> been undone, otherwise there are paths that leave various DRM objects > >> (created by drm_mode_create_standard_properties()) referenced, and > >> will cause problems exactly like you're seeing here. > > > > Liviu, can I leave this with you then? > > That said, I just tried the quick and obvious thing over lunch and it > does *seem* to be OK: Hi Robin, Thanks for tracking this down and for providing a patch. > > ----->8----- > From: Robin Murphy <robin.murphy@arm.com> > Subject: [PATCH] drm: hdlcd: Fix cleanup order > > If hdlcd_drm_bind() fails at drm_fbdev_cma_init(), its cleanup will call > drm_mode_config_cleanup() as if to balance drm_mode_config_reset(). The > net result is that drm_connector_cleanup() will clean up the active > connectors long before component_unbind_all() gets called, so when the > connector later tries to clean up itself after being unbound, Bad Things > can happen: > > [ 4.121888] Unable to handle kernel NULL pointer dereference at > virtual address 00000000 > [ 4.129951] pgd = ffffff80091e0000 > [ 4.133345] [00000000] *pgd=00000009ffffe003, *pud=00000009ffffe003, > *pmd=0000000000000000 > [ 4.141613] Internal error: Oops: 96000005 [#1] PREEMPT SMP > [ 4.147144] Modules linked in: > [ 4.150188] CPU: 0 PID: 122 Comm: kworker/u12:2 Not tainted > 4.8.0-rc2+ #989 > [ 4.157097] Hardware name: ARM Juno development board (r1) (DT) > [ 4.162981] Workqueue: deferwq deferred_probe_work_func > [ 4.168173] task: ffffffc975d93200 task.stack: ffffffc975dac000 > [ 4.174055] PC is at drm_connector_cleanup+0x58/0x1c0 > [ 4.179074] LR is at tda998x_unbind+0x24/0x40 > [ 4.183401] pc : [<ffffff80084c46f0>] lr : [<ffffff800850414c>] > pstate: 00000045 > [ 4.190750] sp : ffffffc975dafa10 > [ 4.194041] x29: ffffffc975dafa10 x28: ffffffc9768152a8 > [ 4.199325] x27: ffffffc97ff46450 x26: ffffff8008d99000 > [ 4.204608] x25: dead000000000100 x24: dead000000000200 > [ 4.209891] x23: ffffffc976bf91e8 x22: 0000000000000000 > [ 4.215172] x21: ffffffc976bf9170 x20: ffffffc976bf9170 > [ 4.220454] x19: ffffffc976bf9018 x18: 0000000000000000 > [ 4.225737] x17: 0000000074ce71ee x16: 000000008ff5d35f > [ 4.231019] x15: ffffffc97681e91c x14: ffffffffffffffff > [ 4.236301] x13: ffffffc97681e185 x12: 0000000000000038 > [ 4.241583] x11: 0101010101010101 x10: 0000000000000000 > [ 4.246866] x9 : 0000000040000000 x8 : 0000000000210d00 > [ 4.252148] x7 : ffffffc97fea8c00 x6 : 000000000000001b > [ 4.257430] x5 : ffffff80084b7b8c x4 : 0000000000000080 > [ 4.262712] x3 : ffffff8008504128 x2 : ffffffc975df3800 > [ 4.267993] x1 : 0000000000000000 x0 : 0000000000000000 > ... > [ 4.750937] [<ffffff80084c46f0>] drm_connector_cleanup+0x58/0x1c0 > [ 4.756990] [<ffffff800850414c>] tda998x_unbind+0x24/0x40 > [ 4.762354] [<ffffff8008507918>] component_unbind.isra.4+0x28/0x50 > [ 4.768492] [<ffffff8008507a0c>] component_unbind_all+0xcc/0xd8 > [ 4.774373] [<ffffff80084d5adc>] hdlcd_drm_bind+0x234/0x418 > [ 4.779909] [<ffffff8008507b58>] try_to_bring_up_master+0x140/0x1a0 > [ 4.786133] [<ffffff8008507c50>] component_add+0x98/0x170 > [ 4.791496] [<ffffff8008504b90>] tda998x_probe+0x18/0x20 > [ 4.796774] [<ffffff80086bf914>] i2c_device_probe+0x164/0x258 > [ 4.802481] [<ffffff800850d094>] driver_probe_device+0x204/0x2b0 > [ 4.808447] [<ffffff800850d28c>] __device_attach_driver+0x9c/0xf8 > [ 4.814498] [<ffffff800850b108>] bus_for_each_drv+0x58/0x98 > [ 4.820033] [<ffffff800850cd64>] __device_attach+0xc4/0x138 > [ 4.825567] [<ffffff800850d338>] device_initial_probe+0x10/0x18 > [ 4.831446] [<ffffff800850c124>] bus_probe_device+0x94/0xa0 > [ 4.836981] [<ffffff800850c5b0>] deferred_probe_work_func+0x78/0xb0 > [ 4.843207] [<ffffff80080d2998>] process_one_work+0x118/0x378 > [ 4.848914] [<ffffff80080d2c40>] worker_thread+0x48/0x498 > [ 4.854276] [<ffffff80080d8918>] kthread+0xd0/0xe8 > [ 4.859036] [<ffffff8008082e90>] ret_from_fork+0x10/0x40 > [ 4.864314] Code: f2fbd5b9 f2fbd5b8 f8478ee0 eb17001f (f9400013) > [ 4.870472] ---[ end trace a643cfe4ce1d838b ]--- > > Fix this by moving the drm_mode_config_cleanup() much later such that it > correctly balances drm_mode_config_init(). > > Suggested-by: Russell King <linux@armlinux.org.uk> > Signed-off-by: Robin Murphy <robin.murphy@arm.com> Acked-by: Liviu Dudau <Liviu.Dudau@arm.com> Best regards, Liviu > --- > drivers/gpu/drm/arm/hdlcd_drv.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c > b/drivers/gpu/drm/arm/hdlcd_drv.c > index 59b76054edc9..1a4fff7c0a7c 100644 > --- a/drivers/gpu/drm/arm/hdlcd_drv.c > +++ b/drivers/gpu/drm/arm/hdlcd_drv.c > @@ -420,7 +420,6 @@ static int hdlcd_drm_bind(struct device *dev) > > err_fbdev: > drm_kms_helper_poll_fini(drm); > - drm_mode_config_cleanup(drm); > drm_vblank_cleanup(drm); > err_vblank: > pm_runtime_disable(drm->dev); > @@ -432,6 +431,7 @@ static int hdlcd_drm_bind(struct device *dev) > drm_irq_uninstall(drm); > of_reserved_mem_device_release(drm->dev); > err_free: > + drm_mode_config_cleanup(drm); > dev_set_drvdata(dev, NULL); > drm_dev_unref(drm); > > -- > 2.10.2.dirty > -- ==================== | I would like to | | fix the world, | | but they're not | | giving me the | \ source code! / --------------- ?\_(?)_/? ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-11-24 14:51 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-11-24 13:18 TDA998x crash on HDLCD probe failure Robin Murphy 2016-11-24 13:29 ` Russell King - ARM Linux 2016-11-24 13:49 ` Robin Murphy 2016-11-24 14:40 ` Robin Murphy 2016-11-24 14:51 ` Liviu Dudau
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).