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

drm/panfrost: Make sure a BO is only unmapped when appropriate

mmu_ops->unmap() will fail when called on a BO that has not been
previously mapped, and the error path in panfrost_ioctl_create_bo()
can call drm_gem_object_put_unlocked() (which in turn calls
panfrost_mmu_unmap()) on a BO that has not been mapped yet.

Keep track of the mapped/unmapped state to avoid such issues.

Fixes: f3ba91228e8e ("drm/panfrost: Add initial panfrost driver")
Cc: <stable@vger.kernel.org>
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20190618081343.16927-1-boris.brezillon@collabora.com

authored by

Boris Brezillon and committed by
Rob Herring
9870dc39 48eaeb76

+11 -1
+2 -1
drivers/gpu/drm/panfrost/panfrost_gem.c
··· 19 19 struct panfrost_gem_object *bo = to_panfrost_bo(obj); 20 20 struct panfrost_device *pfdev = obj->dev->dev_private; 21 21 22 - panfrost_mmu_unmap(bo); 22 + if (bo->is_mapped) 23 + panfrost_mmu_unmap(bo); 23 24 24 25 spin_lock(&pfdev->mm_lock); 25 26 drm_mm_remove_node(&bo->node);
+1
drivers/gpu/drm/panfrost/panfrost_gem.h
··· 11 11 struct drm_gem_shmem_object base; 12 12 13 13 struct drm_mm_node node; 14 + bool is_mapped; 14 15 }; 15 16 16 17 static inline
+8
drivers/gpu/drm/panfrost/panfrost_mmu.c
··· 156 156 struct sg_table *sgt; 157 157 int ret; 158 158 159 + if (WARN_ON(bo->is_mapped)) 160 + return 0; 161 + 159 162 sgt = drm_gem_shmem_get_pages_sgt(obj); 160 163 if (WARN_ON(IS_ERR(sgt))) 161 164 return PTR_ERR(sgt); ··· 192 189 193 190 pm_runtime_mark_last_busy(pfdev->dev); 194 191 pm_runtime_put_autosuspend(pfdev->dev); 192 + bo->is_mapped = true; 195 193 196 194 return 0; 197 195 } ··· 206 202 size_t len = bo->node.size << PAGE_SHIFT; 207 203 size_t unmapped_len = 0; 208 204 int ret; 205 + 206 + if (WARN_ON(!bo->is_mapped)) 207 + return; 209 208 210 209 dev_dbg(pfdev->dev, "unmap: iova=%llx, len=%zx", iova, len); 211 210 ··· 237 230 238 231 pm_runtime_mark_last_busy(pfdev->dev); 239 232 pm_runtime_put_autosuspend(pfdev->dev); 233 + bo->is_mapped = false; 240 234 } 241 235 242 236 static void mmu_tlb_inv_context_s1(void *cookie)