Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm: fix locking inconsistencies in gpu->destroy()

In error paths, this was being called without struct_mutex held.
Leading to panics like:

msm 1a00000.qcom,mdss_mdp: No memory protection without IOMMU
Kernel panic - not syncing: BUG!
CPU: 0 PID: 1409 Comm: cat Not tainted 4.0.0-dirty #4
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
Call trace:
[<ffffffc000089c78>] dump_backtrace+0x0/0x118
[<ffffffc000089da0>] show_stack+0x10/0x20
[<ffffffc0006686d4>] dump_stack+0x84/0xc4
[<ffffffc0006678b4>] panic+0xd0/0x210
[<ffffffc0003e1ce4>] drm_gem_object_free+0x5c/0x60
[<ffffffc000402870>] adreno_gpu_cleanup+0x60/0x80
[<ffffffc0004035a0>] a3xx_destroy+0x20/0x70
[<ffffffc0004036f4>] a3xx_gpu_init+0x84/0x108
[<ffffffc0004018b8>] adreno_load_gpu+0x58/0x190
[<ffffffc000419dac>] msm_open+0x74/0x88
[<ffffffc0003e0a48>] drm_open+0x168/0x400
[<ffffffc0003e7210>] drm_stub_open+0xa8/0x118
[<ffffffc0001a0e84>] chrdev_open+0x94/0x198
[<ffffffc000199f88>] do_dentry_open+0x208/0x310
[<ffffffc00019a4c4>] vfs_open+0x44/0x50
[<ffffffc0001aa26c>] do_last.isra.14+0x2c4/0xc10
[<ffffffc0001aac38>] path_openat+0x80/0x5e8
[<ffffffc0001ac354>] do_filp_open+0x2c/0x98
[<ffffffc00019b60c>] do_sys_open+0x13c/0x228
[<ffffffc00019b72c>] SyS_openat+0xc/0x18
CPU1: stopping

But there isn't any particularly good reason to hold struct_mutex for
teardown, so just standardize on calling it without the mutex held and
use the _unlocked() versions for GEM obj unref'ing

Signed-off-by: Rob Clark <robdclark@gmail.com>

Rob Clark 774449eb ec1936eb

+3 -3
+1 -1
drivers/gpu/drm/msm/adreno/adreno_gpu.c
··· 384 384 if (gpu->memptrs_bo) { 385 385 if (gpu->memptrs_iova) 386 386 msm_gem_put_iova(gpu->memptrs_bo, gpu->base.id); 387 - drm_gem_object_unreference(gpu->memptrs_bo); 387 + drm_gem_object_unreference_unlocked(gpu->memptrs_bo); 388 388 } 389 389 release_firmware(gpu->pm4); 390 390 release_firmware(gpu->pfp);
+1 -1
drivers/gpu/drm/msm/msm_drv.c
··· 145 145 if (gpu) { 146 146 mutex_lock(&dev->struct_mutex); 147 147 gpu->funcs->pm_suspend(gpu); 148 - gpu->funcs->destroy(gpu); 149 148 mutex_unlock(&dev->struct_mutex); 149 + gpu->funcs->destroy(gpu); 150 150 } 151 151 152 152 if (priv->vram.paddr) {
+1 -1
drivers/gpu/drm/msm/msm_ringbuffer.c
··· 56 56 void msm_ringbuffer_destroy(struct msm_ringbuffer *ring) 57 57 { 58 58 if (ring->bo) 59 - drm_gem_object_unreference(ring->bo); 59 + drm_gem_object_unreference_unlocked(ring->bo); 60 60 kfree(ring); 61 61 }