From: Russell King <rmk+ker...@arm.linux.org.uk> The oops below was found when unbinding the etnaviv drm driver. This is caused by using drm_gem_object_unreference() in a region which is not protected by drm_dev->struct_mutex. Fix this by using drm_gem_object_unreference_unlocked() instead.
Kernel BUG at c026cab8 [verbose debug info unavailable] Internal error: Oops - BUG: 0 [#1] PREEMPT ARM Modules linked in: etnaviv(C-) ... task: d41dda80 ti: d63f2000 task.ti: d63f2000 PC is at drm_gem_object_free+0x34/0x38 LR is at etnaviv_gpu_unbind+0x7c/0xb0 [etnaviv] pc : [<c026cab8>] lr : [<bf1067a8>] psr: 600d0013 sp : d63f3da0 ip : d63f3db0 fp : d63f3dac r10: 00020000 r9 : d63f2000 r8 : c000ece8 r7 : d4386c34 r6 : d4386c00 r5 : d42c4d80 r4 : d621ac10 r3 : d4386c00 r2 : 00000001 r1 : d608c410 r0 : d59da580 Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: 14234019 DAC: 00000015 Process rmmod (pid: 1633, stack limit = 0xd63f2250) [<c026ca84>] (drm_gem_object_free) from [<bf1067a8>] (etnaviv_gpu_unbind+0x7c/0xb0 [etnaviv]) [<bf10672c>] (etnaviv_gpu_unbind [etnaviv]) from [<c028a47c>] (component_unbind+0x38/0x70) [<c028a444>] (component_unbind) from [<c028a52c>] (component_unbind_all+0x78/0xac) [<c028a4b4>] (component_unbind_all) from [<bf104560>] (etnaviv_unload+0x68/0x7c [etnaviv]) [<bf1044f8>] (etnaviv_unload [etnaviv]) from [<c0270498>] (drm_dev_unregister+0x2c/0xa0) [<c0270c90>] (drm_put_dev) from [<bf104058>] (etnaviv_unbind+0x14/0x18 [etnaviv]) [<bf104044>] (etnaviv_unbind [etnaviv]) from [<c028a2a4>] (take_down_master+0x2c/0x4c) ... Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk> --- drivers/staging/etnaviv/etnaviv_gpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/etnaviv/etnaviv_gpu.c b/drivers/staging/etnaviv/etnaviv_gpu.c index e3b93c293dca..8e44493038cb 100644 --- a/drivers/staging/etnaviv/etnaviv_gpu.c +++ b/drivers/staging/etnaviv/etnaviv_gpu.c @@ -868,7 +868,7 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master, WARN_ON(!list_empty(&gpu->active_list)); if (gpu->buffer) - drm_gem_object_unreference(gpu->buffer); + drm_gem_object_unreference_unlocked(gpu->buffer); if (gpu->mmu) etnaviv_iommu_destroy(gpu->mmu); -- 2.1.4