summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drm_bo_move.c71
-rw-r--r--linux-core/drm_objects.h2
2 files changed, 73 insertions, 0 deletions
diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c
index e81967fd..207a5e07 100644
--- a/linux-core/drm_bo_move.c
+++ b/linux-core/drm_bo_move.c
@@ -272,6 +272,77 @@ out:
}
EXPORT_SYMBOL(drm_bo_move_memcpy);
+static int drm_memset_io_page(void *dst, unsigned long page)
+{
+ dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT));
+ memset_io(dst, 0, PAGE_SIZE);
+ return 0;
+}
+
+static int drm_memset_ttm_page(struct drm_ttm *ttm, unsigned long page)
+{
+ struct page *d = drm_ttm_get_page(ttm, page);
+ void *dst;
+
+ dst = kmap(d);
+ if (!dst)
+ return -ENOMEM;
+
+ memset_io(dst, 0, PAGE_SIZE);
+ kunmap(d);
+ return 0;
+}
+
+int drm_bo_move_zero(struct drm_buffer_object *bo,
+ int evict, int no_wait, struct drm_bo_mem_reg *new_mem)
+{
+ struct drm_device *dev = bo->dev;
+ struct drm_mem_type_manager *man = &dev->bm.man[new_mem->mem_type];
+ struct drm_ttm *ttm = bo->ttm;
+ void *new_iomap;
+ int ret;
+ struct drm_bo_mem_reg *old_mem = &bo->mem;
+ uint64_t save_flags = old_mem->flags;
+ uint64_t save_proposed_flags = old_mem->proposed_flags;
+ unsigned long i;
+ unsigned long page;
+
+ ret = drm_mem_reg_ioremap(dev, new_mem, &new_iomap);
+ if (ret)
+ goto out;
+
+ if (new_iomap == NULL && ttm == NULL)
+ goto out2;
+
+ for (i = 0; i < new_mem->num_pages; ++i) {
+ if (new_iomap == NULL)
+ ret = drm_memset_ttm_page(ttm, i);
+ else
+ ret = drm_memset_io_page(new_iomap, i);
+ if (ret)
+ goto out1;
+ }
+ mb();
+out2:
+ drm_bo_free_old_node(bo);
+
+ *old_mem = *new_mem;
+ new_mem->mm_node = NULL;
+ old_mem->proposed_flags = save_proposed_flags;
+ DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE);
+
+ if ((man->flags & _DRM_FLAG_MEMTYPE_FIXED) && (ttm != NULL)) {
+ drm_ttm_unbind(ttm);
+ drm_ttm_destroy(ttm);
+ bo->ttm = NULL;
+ }
+out1:
+ drm_mem_reg_iounmap(dev, new_mem, new_iomap);
+out:
+ return ret;
+}
+EXPORT_SYMBOL(drm_bo_move_zero);
+
/*
* Transfer a buffer object's memory and LRU status to a newly
* created object. User-space references remains with the old
diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h
index 2493a804..e13475a2 100644
--- a/linux-core/drm_objects.h
+++ b/linux-core/drm_objects.h
@@ -808,6 +808,8 @@ extern int drm_bo_move_ttm(struct drm_buffer_object *bo,
extern int drm_bo_move_memcpy(struct drm_buffer_object *bo,
int evict,
int no_wait, struct drm_bo_mem_reg *new_mem);
+extern int drm_bo_move_zero(struct drm_buffer_object *bo,
+ int evict, int no_wait, struct drm_bo_mem_reg *new_mem);
extern int drm_bo_move_accel_cleanup(struct drm_buffer_object *bo,
int evict, int no_wait,
uint32_t fence_class, uint32_t fence_type,