From 6cbe6c4e1d16049e05e4398a30a4418d7fc64636 Mon Sep 17 00:00:00 2001 From: Sandy Huang Date: Fri, 11 Feb 2022 11:12:31 +0800 Subject: [PATCH] drm/rockchip: logo: add mutex lock protect for drm mm node [02-10 13:20:47][ 6.774909][ T399] ------------[ cut here ]------------ [02-10 13:20:47][ 6.775778][ T399] kernel BUG at lib/list_debug.c:56! [02-10 13:20:47][ 6.776233][ T399] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP [02-10 13:20:47][ 6.776776][ T399] Modules linked in: bcmdhd r8168 [02-10 13:20:47][ 6.777203][ T399] CPU: 4 PID: 399 Comm: HwBinder:379_2 Not tainted 5.10.66 #1083 [02-10 13:20:47][ 6.777865][ T399] Hardware name: Rockchip RK3588 EVB1 LP4 V10 Board (DT) [02-10 13:20:47][ 6.778463][ T399] pstate: 60400009 (nZCv daif +PAN UAO -TCO BTYPE=-) [02-10 13:20:47][ 6.779051][ T399] pc : __list_del_entry_valid+0xa8/0xac [02-10 13:20:47][ 6.779528][ T399] lr : __list_del_entry_valid+0xa8/0xac ... [02-10 13:20:47][ 6.788175][ T399] Call trace: [02-10 13:20:47][ 6.788448][ T399] __list_del_entry_valid+0xa8/0xac [02-10 13:20:47][ 6.788894][ T399] rm_hole+0x24/0x2bc [02-10 13:20:47][ 6.789231][ T399] drm_mm_insert_node_in_range+0x614/0x64c [02-10 13:20:47][ 6.789731][ T399] rockchip_gem_iommu_map+0x5c/0x164 [02-10 13:20:47][ 6.790186][ T399] rockchip_gem_prime_import_sg_table+0x9c/0x1c8 [02-10 13:20:47][ 6.790729][ T399] rockchip_drm_gem_prime_import_dev+0xc4/0x17c [02-10 13:20:47][ 6.791260][ T399] rockchip_drm_gem_prime_import+0x18/0x28 [02-10 13:20:47][ 6.791758][ T399] drm_gem_prime_fd_to_handle+0x9c/0x1f4 [02-10 13:20:47][ 6.792235][ T399] drm_prime_fd_to_handle_ioctl+0x30/0x48 [02-10 13:20:47][ 6.792723][ T399] drm_ioctl+0x24c/0x3b8 [02-10 13:20:47][ 6.793084][ T399] __arm64_sys_ioctl+0x94/0xd0 [02-10 13:20:47][ 6.793487][ T399] el0_svc_common+0xb8/0x1a4 [02-10 13:20:47][ 6.793878][ T399] do_el0_svc+0x28/0x88 [02-10 13:20:47][ 6.794228][ T399] el0_svc+0x14/0x24 [02-10 13:20:47][ 6.794554][ T399] el0_sync_handler+0x88/0xec [02-10 13:20:47][ 6.794955][ T399] el0_sync+0x1a8/0x1c0 Signed-off-by: Sandy Huang Change-Id: Ifd0ec4628d3afb4a2337998737c6e0ba7b6c52ca --- drivers/gpu/drm/rockchip/rockchip_drm_logo.c | 21 +++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c index 4c8fbd656a8c..2f0a393e934b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c @@ -121,21 +121,28 @@ err_put_encoder: return sub_dev; } -static void rockchip_drm_release_reserve_vm(struct drm_mm_node *node) +static void rockchip_drm_release_reserve_vm(struct drm_device *drm, struct drm_mm_node *node) { + struct rockchip_drm_private *private = drm->dev_private; + + mutex_lock(&private->mm_lock); if (drm_mm_node_allocated(node)) drm_mm_remove_node(node); + mutex_unlock(&private->mm_lock); } -static int rockchip_drm_reserve_vm(struct drm_mm *mm, +static int rockchip_drm_reserve_vm(struct drm_device *drm, struct drm_mm *mm, struct drm_mm_node *node, u64 size, u64 offset) { + struct rockchip_drm_private *private = drm->dev_private; int ret; node->size = size; node->start = offset; node->color = 0; + mutex_lock(&private->mm_lock); ret = drm_mm_reserve_node(mm, node); + mutex_unlock(&private->mm_lock); return ret; } @@ -194,7 +201,7 @@ void rockchip_free_loader_memory(struct drm_device *drm) u32 pg_size = 1UL << __ffs(private->domain->pgsize_bitmap); iommu_unmap(private->domain, logo->dma_addr, ALIGN(logo->size, pg_size)); - rockchip_drm_release_reserve_vm(&logo->logo_reserved_node); + rockchip_drm_release_reserve_vm(drm, &logo->logo_reserved_node); } memblock_free(logo->start, logo->size); @@ -240,7 +247,7 @@ static int init_loader_memory(struct drm_device *drm_dev) logo->kvaddr = phys_to_virt(start); if (private->domain) { - ret = rockchip_drm_reserve_vm(&private->mm, &logo->logo_reserved_node, size, start); + ret = rockchip_drm_reserve_vm(drm_dev, &private->mm, &logo->logo_reserved_node, size, start); if (ret) dev_err(drm_dev->dev, "failed to reserve vm for logo memory\n"); ret = iommu_map(private->domain, start, start, ALIGN(size, pg_size), @@ -278,7 +285,7 @@ static int init_loader_memory(struct drm_device *drm_dev) if (!private->clut_reserved_node) return -ENOMEM; - ret = rockchip_drm_reserve_vm(&private->mm, private->clut_reserved_node, size, start); + ret = rockchip_drm_reserve_vm(drm_dev, &private->mm, private->clut_reserved_node, size, start); if (ret) dev_err(drm_dev->dev, "failed to reserve vm for clut memory\n"); @@ -294,11 +301,11 @@ static int init_loader_memory(struct drm_device *drm_dev) return 0; err_free_clut: - rockchip_drm_release_reserve_vm(private->clut_reserved_node); + rockchip_drm_release_reserve_vm(drm_dev, private->clut_reserved_node); kfree(private->clut_reserved_node); private->clut_reserved_node = NULL; err_free_logo: - rockchip_drm_release_reserve_vm(&logo->logo_reserved_node); + rockchip_drm_release_reserve_vm(drm_dev, &logo->logo_reserved_node); kfree(logo); return ret;