diff --git a/sys/dev/drm2/drmP.h b/sys/dev/drm2/drmP.h index dbf5277..4f86372 100644 --- a/sys/dev/drm2/drmP.h +++ b/sys/dev/drm2/drmP.h @@ -1432,6 +1432,8 @@ void drm_gem_pager_dtr(void *obj); struct ttm_bo_device; int ttm_bo_mmap_single(struct ttm_bo_device *bdev, vm_ooffset_t *offset, vm_size_t size, struct vm_object **obj_res, int nprot); +struct ttm_buffer_object; +void ttm_bo_mmap_release(struct ttm_buffer_object *bo); void drm_device_lock_mtx(struct drm_device *dev); void drm_device_unlock_mtx(struct drm_device *dev); diff --git a/sys/dev/drm2/ttm/ttm_bo.c b/sys/dev/drm2/ttm/ttm_bo.c index 8bd8af9..8676113 100644 --- a/sys/dev/drm2/ttm/ttm_bo.c +++ b/sys/dev/drm2/ttm/ttm_bo.c @@ -523,6 +523,8 @@ static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) bo->bdev->driver->move_notify(bo, NULL); if (bo->ttm) { + ttm_bo_mmap_release(bo); + ttm_tt_unbind(bo->ttm); ttm_tt_destroy(bo->ttm); bo->ttm = NULL; diff --git a/sys/dev/drm2/ttm/ttm_bo_util.c b/sys/dev/drm2/ttm/ttm_bo_util.c index bca0ad3..e334ac3 100644 --- a/sys/dev/drm2/ttm/ttm_bo_util.c +++ b/sys/dev/drm2/ttm/ttm_bo_util.c @@ -655,8 +655,19 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED)) ghost_obj->ttm = NULL; - else + else { + /* + * Release mmap for this buffer object, because + * bo->ttm is transferred to the ghost object. + * + * ttm_bo_mmap_release() will be called again + * on ghost_obj but it'll be a no-op, as the + * vm_object_t is already deallocated. + */ + ttm_bo_mmap_release(bo); + bo->ttm = NULL; + } ttm_bo_unreserve(ghost_obj); ttm_bo_unref(&ghost_obj); diff --git a/sys/dev/drm2/ttm/ttm_bo_vm.c b/sys/dev/drm2/ttm/ttm_bo_vm.c index 2eba4c3..eef4d7f 100644 --- a/sys/dev/drm2/ttm/ttm_bo_vm.c +++ b/sys/dev/drm2/ttm/ttm_bo_vm.c @@ -337,6 +337,32 @@ out_unref: return ret; } +void +ttm_bo_mmap_release(struct ttm_buffer_object *bo) +{ + vm_object_t vm_obj; + vm_page_t m; + int i; + + vm_obj = cdev_pager_lookup(bo); + if (vm_obj == NULL) { + return; + } + + VM_OBJECT_WLOCK(vm_obj); +retry: + for (i = 0; i < bo->num_pages; i++) { + m = vm_page_lookup(vm_obj, i); + if (m == NULL) + continue; + if (vm_page_sleep_if_busy(m, true, "ttm_unm")) + goto retry; + cdev_pager_free_page(vm_obj, m); + } + VM_OBJECT_WUNLOCK(vm_obj); + vm_object_deallocate(vm_obj); +} + #if 0 int ttm_fbdev_mmap(struct vm_area_struct *vma, struct ttm_buffer_object *bo) {