Skip to content

Commit 9786b65

Browse files
committed
drm/ttm: fix mmap refcounting
When mapping ttm objects via drm_gem_ttm_mmap() helper drm_gem_mmap_obj() will take an object reference. That gets never released due to ttm having its own reference counting. Fix that by dropping the gem object reference once the ttm mmap completed (and ttm refcount got bumped). For that to work properly the drm_gem_object_get() call in drm_gem_ttm_mmap() must be moved so it happens before calling obj->funcs->mmap(), otherwise the gem refcount would go down to zero. Fixes: 231927d ("drm/ttm: add drm_gem_ttm_mmap()") Signed-off-by: Gerd Hoffmann <[email protected]> Reviewed-by: Daniel Vetter <[email protected]> Tested-by: Thomas Zimmermann <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent a64fc11 commit 9786b65

File tree

2 files changed

+26
-11
lines changed

2 files changed

+26
-11
lines changed

drivers/gpu/drm/drm_gem.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,21 +1105,33 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
11051105
if (obj_size < vma->vm_end - vma->vm_start)
11061106
return -EINVAL;
11071107

1108+
/* Take a ref for this mapping of the object, so that the fault
1109+
* handler can dereference the mmap offset's pointer to the object.
1110+
* This reference is cleaned up by the corresponding vm_close
1111+
* (which should happen whether the vma was created by this call, or
1112+
* by a vm_open due to mremap or partial unmap or whatever).
1113+
*/
1114+
drm_gem_object_get(obj);
1115+
11081116
if (obj->funcs && obj->funcs->mmap) {
11091117
/* Remove the fake offset */
11101118
vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
11111119

11121120
ret = obj->funcs->mmap(obj, vma);
1113-
if (ret)
1121+
if (ret) {
1122+
drm_gem_object_put_unlocked(obj);
11141123
return ret;
1124+
}
11151125
WARN_ON(!(vma->vm_flags & VM_DONTEXPAND));
11161126
} else {
11171127
if (obj->funcs && obj->funcs->vm_ops)
11181128
vma->vm_ops = obj->funcs->vm_ops;
11191129
else if (dev->driver->gem_vm_ops)
11201130
vma->vm_ops = dev->driver->gem_vm_ops;
1121-
else
1131+
else {
1132+
drm_gem_object_put_unlocked(obj);
11221133
return -EINVAL;
1134+
}
11231135

11241136
vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
11251137
vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
@@ -1128,14 +1140,6 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
11281140

11291141
vma->vm_private_data = obj;
11301142

1131-
/* Take a ref for this mapping of the object, so that the fault
1132-
* handler can dereference the mmap offset's pointer to the object.
1133-
* This reference is cleaned up by the corresponding vm_close
1134-
* (which should happen whether the vma was created by this call, or
1135-
* by a vm_open due to mremap or partial unmap or whatever).
1136-
*/
1137-
drm_gem_object_get(obj);
1138-
11391143
return 0;
11401144
}
11411145
EXPORT_SYMBOL(drm_gem_mmap_obj);

drivers/gpu/drm/drm_gem_ttm_helper.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,19 @@ int drm_gem_ttm_mmap(struct drm_gem_object *gem,
6464
struct vm_area_struct *vma)
6565
{
6666
struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
67+
int ret;
6768

68-
return ttm_bo_mmap_obj(vma, bo);
69+
ret = ttm_bo_mmap_obj(vma, bo);
70+
if (ret < 0)
71+
return ret;
72+
73+
/*
74+
* ttm has its own object refcounting, so drop gem reference
75+
* to avoid double accounting counting.
76+
*/
77+
drm_gem_object_put_unlocked(gem);
78+
79+
return 0;
6980
}
7081
EXPORT_SYMBOL(drm_gem_ttm_mmap);
7182

0 commit comments

Comments
 (0)