From 71e3dfa167b105d3c06e76fee1d0e2fd1e502cf6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 10 Jul 2017 10:20:42 +0300 Subject: drm/msm: unlock on error in msm_gem_get_iova() We recently added locking to this function but there was a direct return that was overlooked where we need to unlock. Fixes: 0e08270a1f01 ("drm/msm: Separate locking of buffer resources from struct_mutex") Signed-off-by: Dan Carpenter Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/msm/msm_gem.c') diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 65f35544c1ec..065d933df2c3 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -383,8 +383,10 @@ int msm_gem_get_iova(struct drm_gem_object *obj, struct page **pages; vma = add_vma(obj, aspace); - if (IS_ERR(vma)) - return PTR_ERR(vma); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto unlock; + } pages = get_pages(obj); if (IS_ERR(pages)) { @@ -405,7 +407,7 @@ int msm_gem_get_iova(struct drm_gem_object *obj, fail: del_vma(vma); - +unlock: mutex_unlock(&msm_obj->lock); return ret; } -- cgit v1.2.3 From b3949a9a3e09f87e0371e80a2bef6ec0d48b575d Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 30 Jul 2017 14:42:36 +0200 Subject: drm/msm: fix WARN_ON in add_vma() with no iommu While I was testing the upcoming adv7533 CEC support with my Dragonboard c410 I encountered this warning several times during boot: [ 4.408309] WARNING: CPU: 3 PID: 1347 at drivers/gpu/drm/msm/msm_gem.c:312 add_vma+0x78/0x88 [msm] [ 4.412951] Modules linked in: snd_soc_hdmi_codec adv7511 cec qcom_wcnss_pil msm mdt_loader drm_kms_helper msm_rng rng_core drm [ 4.421728] CPU: 3 PID: 1347 Comm: kworker/3:3 Not tainted 4.13.0-rc1-dragonboard #111 [ 4.433090] Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT) [ 4.441081] Workqueue: events deferred_probe_work_func [ 4.447929] task: ffff800031243600 task.stack: ffff800003394000 [ 4.453023] PC is at add_vma+0x78/0x88 [msm] [ 4.458823] LR is at _msm_gem_new+0xd4/0x188 [msm] [ 4.463207] pc : [] lr : [] pstate: 40000145 [ 4.467811] sp : ffff8000033978a0 [ 4.475357] x29: ffff8000033978a0 x28: ffff8000031dea18 [ 4.478572] x27: ffff800003933a00 x26: ffff800003b39800 [ 4.483953] x25: ffff8000338ff800 x24: 0000000000000001 [ 4.489249] x23: 0000000000000000 x22: ffff800003b39800 [ 4.494544] x21: ffff8000338ff800 x20: 0000000000000000 [ 4.499839] x19: ffff800003932600 x18: 0000000000000001 [ 4.505135] x17: 0000ffff8969e9e0 x16: ffff7e00000ce7a0 [ 4.510429] x15: ffffffffffffffff x14: ffff8000833977ef [ 4.515724] x13: ffff8000033977f3 x12: 0000000000000038 [ 4.521020] x11: 0101010101010101 x10: ffffff7f7fff7f7f [ 4.526315] x9 : 0000000000000000 x8 : ffff800003932800 [ 4.531633] x7 : 0000000000000000 x6 : 000000000000003f [ 4.531644] x5 : 0000000000000040 x4 : 0000000000000000 [ 4.531650] x3 : ffff800031243600 x2 : 0000000000000000 [ 4.531655] x1 : 0000000000000000 x0 : 0000000000000000 [ 4.531670] Call trace: [ 4.531676] Exception stack(0xffff8000033976c0 to 0xffff8000033977f0) [ 4.531683] 76c0: ffff800003932600 0001000000000000 ffff8000033978a0 ffff000000ac01f8 [ 4.531688] 76e0: 0000000000000140 0000000000000000 ffff800003932550 ffff800003397780 [ 4.531694] 7700: ffff800003397730 ffff000008261ce8 0000000000000000 ffff8000031d2f80 [ 4.531699] 7720: ffff800003397800 ffff0000081d671c 0000000000000140 0000000000000000 [ 4.531705] 7740: ffff000000ac04c0 0000000000004003 ffff800003397908 00000000014080c0 [ 4.531710] 7760: 0000000000000000 ffff800003b39800 0000000000000000 0000000000000000 [ 4.531716] 7780: 0000000000000000 ffff800031243600 0000000000000000 0000000000000040 [ 4.531721] 77a0: 000000000000003f 0000000000000000 ffff800003932800 0000000000000000 [ 4.531726] 77c0: ffffff7f7fff7f7f 0101010101010101 0000000000000038 ffff8000033977f3 [ 4.531730] 77e0: ffff8000833977ef ffffffffffffffff [ 4.531881] [] add_vma+0x78/0x88 [msm] [ 4.532011] [] _msm_gem_new+0xd4/0x188 [msm] [ 4.532134] [] msm_gem_new+0x10/0x18 [msm] [ 4.532260] [] msm_dsi_host_modeset_init+0x17c/0x268 [msm] [ 4.532384] [] msm_dsi_modeset_init+0x34/0x1b8 [msm] [ 4.532504] [] modeset_init+0x408/0x488 [msm] [ 4.532623] [] mdp5_kms_init+0x2b4/0x338 [msm] [ 4.532745] [] msm_drm_bind+0x218/0x4e8 [msm] [ 4.532755] [] try_to_bring_up_master+0x1f4/0x318 [ 4.532762] [] component_add+0x98/0x180 [ 4.532887] [] dsi_dev_probe+0x18/0x28 [msm] [ 4.532895] [] platform_drv_probe+0x58/0xc0 [ 4.532901] [] driver_probe_device+0x324/0x458 [ 4.532907] [] __device_attach_driver+0xac/0x170 [ 4.532913] [] bus_for_each_drv+0x4c/0x98 [ 4.532918] [] __device_attach+0xc0/0x160 [ 4.532924] [] device_initial_probe+0x10/0x18 [ 4.532929] [] bus_probe_device+0x94/0xa0 [ 4.532934] [] deferred_probe_work_func+0x8c/0xe8 [ 4.532941] [] process_one_work+0x1d4/0x330 [ 4.532946] [] worker_thread+0x48/0x468 [ 4.532952] [] kthread+0x12c/0x130 [ 4.532958] [] ret_from_fork+0x10/0x40 [ 4.532962] ---[ end trace b1ac6888ec40b0bb ]--- Signed-off-by: Hans Verkuil Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_gem.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/msm/msm_gem.c') diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 065d933df2c3..a0c60e738db8 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -930,8 +930,12 @@ static struct drm_gem_object *_msm_gem_new(struct drm_device *dev, if (use_vram) { struct msm_gem_vma *vma; struct page **pages; + struct msm_gem_object *msm_obj = to_msm_bo(obj); + + mutex_lock(&msm_obj->lock); vma = add_vma(obj, NULL); + mutex_unlock(&msm_obj->lock); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto fail; -- cgit v1.2.3 From 8223286d62e296fb762e11894fbdaa84f471915d Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 27 Jul 2017 10:42:40 -0600 Subject: drm/msm: Add a helper function for in-kernel buffer allocations Nearly all of the buffer allocations for kernel allocate an buffer object, virtual address and GPU iova at the same time. Make a helper function to handle the details. Signed-off-by: Jordan Crouse [dropped msm_fbdev conversion to new helper, since it interferes with display-handover work, where we want to separate allocation and mapping] Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 22 +++------------- drivers/gpu/drm/msm/adreno/a5xx_power.c | 14 +++------- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 26 +++++-------------- drivers/gpu/drm/msm/msm_drv.h | 6 +++++ drivers/gpu/drm/msm/msm_gem.c | 46 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/msm_ringbuffer.c | 12 ++++----- 6 files changed, 72 insertions(+), 54 deletions(-) (limited to 'drivers/gpu/drm/msm/msm_gem.c') diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 1f4a0322b127..1e164008f5b9 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -284,28 +284,14 @@ static int a5xx_me_init(struct msm_gpu *gpu) static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu, const struct firmware *fw, u64 *iova) { - struct drm_device *drm = gpu->dev; struct drm_gem_object *bo; void *ptr; - bo = msm_gem_new_locked(drm, fw->size - 4, MSM_BO_UNCACHED); - if (IS_ERR(bo)) - return bo; + ptr = msm_gem_kernel_new_locked(gpu->dev, fw->size - 4, + MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace, &bo, iova); - ptr = msm_gem_get_vaddr(bo); - if (!ptr) { - drm_gem_object_unreference(bo); - return ERR_PTR(-ENOMEM); - } - - if (iova) { - int ret = msm_gem_get_iova(bo, gpu->aspace, iova); - - if (ret) { - drm_gem_object_unreference(bo); - return ERR_PTR(ret); - } - } + if (IS_ERR(ptr)) + return ERR_CAST(ptr); memcpy(ptr, &fw->data[4], fw->size - 4); diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c index 87af6eea0483..04aab1dcae2b 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c @@ -294,16 +294,10 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu) */ bosize = (cmds_size + (cmds_size / TYPE4_MAX_PAYLOAD) + 1) << 2; - a5xx_gpu->gpmu_bo = msm_gem_new_locked(drm, bosize, MSM_BO_UNCACHED); - if (IS_ERR(a5xx_gpu->gpmu_bo)) - goto err; - - if (msm_gem_get_iova(a5xx_gpu->gpmu_bo, gpu->aspace, - &a5xx_gpu->gpmu_iova)) - goto err; - - ptr = msm_gem_get_vaddr(a5xx_gpu->gpmu_bo); - if (!ptr) + ptr = msm_gem_kernel_new_locked(drm, bosize, + MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace, + &a5xx_gpu->gpmu_bo, &a5xx_gpu->gpmu_iova); + if (IS_ERR(ptr)) goto err; while (cmds_size > 0) { diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index f69a903c95af..c8b4ac254bb5 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -391,29 +391,17 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, return ret; } - adreno_gpu->memptrs_bo = msm_gem_new(drm, sizeof(*adreno_gpu->memptrs), - MSM_BO_UNCACHED); - if (IS_ERR(adreno_gpu->memptrs_bo)) { - ret = PTR_ERR(adreno_gpu->memptrs_bo); - adreno_gpu->memptrs_bo = NULL; - dev_err(drm->dev, "could not allocate memptrs: %d\n", ret); - return ret; - } + adreno_gpu->memptrs = msm_gem_kernel_new(drm, + sizeof(*adreno_gpu->memptrs), MSM_BO_UNCACHED, gpu->aspace, + &adreno_gpu->memptrs_bo, &adreno_gpu->memptrs_iova); - adreno_gpu->memptrs = msm_gem_get_vaddr(adreno_gpu->memptrs_bo); if (IS_ERR(adreno_gpu->memptrs)) { - dev_err(drm->dev, "could not vmap memptrs\n"); - return -ENOMEM; - } - - ret = msm_gem_get_iova(adreno_gpu->memptrs_bo, gpu->aspace, - &adreno_gpu->memptrs_iova); - if (ret) { - dev_err(drm->dev, "could not map memptrs: %d\n", ret); - return ret; + ret = PTR_ERR(adreno_gpu->memptrs); + adreno_gpu->memptrs = NULL; + dev_err(drm->dev, "could not allocate memptrs: %d\n", ret); } - return 0; + return ret; } void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index fc8d24f7c084..62ac0871bf14 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -237,6 +237,12 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev, uint32_t size, uint32_t flags); struct drm_gem_object *msm_gem_new_locked(struct drm_device *dev, uint32_t size, uint32_t flags); +void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size, + uint32_t flags, struct msm_gem_address_space *aspace, + struct drm_gem_object **bo, uint64_t *iova); +void *msm_gem_kernel_new_locked(struct drm_device *dev, uint32_t size, + uint32_t flags, struct msm_gem_address_space *aspace, + struct drm_gem_object **bo, uint64_t *iova); struct drm_gem_object *msm_gem_import(struct drm_device *dev, struct dma_buf *dmabuf, struct sg_table *sgt); diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index a0c60e738db8..f15821a0d900 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -1024,3 +1024,49 @@ fail: drm_gem_object_unreference_unlocked(obj); return ERR_PTR(ret); } + +static void *_msm_gem_kernel_new(struct drm_device *dev, uint32_t size, + uint32_t flags, struct msm_gem_address_space *aspace, + struct drm_gem_object **bo, uint64_t *iova, bool locked) +{ + void *vaddr; + struct drm_gem_object *obj = _msm_gem_new(dev, size, flags, locked); + int ret; + + if (IS_ERR(obj)) + return ERR_CAST(obj); + + if (iova) { + ret = msm_gem_get_iova(obj, aspace, iova); + if (ret) { + drm_gem_object_unreference(obj); + return ERR_PTR(ret); + } + } + + vaddr = msm_gem_get_vaddr(obj); + if (!vaddr) { + msm_gem_put_iova(obj, aspace); + drm_gem_object_unreference(obj); + return ERR_PTR(-ENOMEM); + } + + if (bo) + *bo = obj; + + return vaddr; +} + +void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size, + uint32_t flags, struct msm_gem_address_space *aspace, + struct drm_gem_object **bo, uint64_t *iova) +{ + return _msm_gem_kernel_new(dev, size, flags, aspace, bo, iova, false); +} + +void *msm_gem_kernel_new_locked(struct drm_device *dev, uint32_t size, + uint32_t flags, struct msm_gem_address_space *aspace, + struct drm_gem_object **bo, uint64_t *iova) +{ + return _msm_gem_kernel_new(dev, size, flags, aspace, bo, iova, true); +} diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index 791bca3c6a9c..bf065a540130 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -33,16 +33,14 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size) } ring->gpu = gpu; - ring->bo = msm_gem_new(gpu->dev, size, MSM_BO_WC); - if (IS_ERR(ring->bo)) { - ret = PTR_ERR(ring->bo); - ring->bo = NULL; - goto fail; - } - ring->start = msm_gem_get_vaddr(ring->bo); + /* Pass NULL for the iova pointer - we will map it later */ + ring->start = msm_gem_kernel_new(gpu->dev, size, MSM_BO_WC, + gpu->aspace, &ring->bo, NULL); + if (IS_ERR(ring->start)) { ret = PTR_ERR(ring->start); + ring->start = 0; goto fail; } ring->end = ring->start + (size / 4); -- cgit v1.2.3