drm: add move zero function to memset unclean buffers
authorDave Airlie <airlied@redhat.com>
Tue, 26 Aug 2008 07:43:12 +0000 (17:43 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 26 Aug 2008 07:43:12 +0000 (17:43 +1000)
linux-core/drm_bo_move.c
linux-core/drm_objects.h

index e81967f..207a5e0 100644 (file)
@@ -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
index 2493a80..e13475a 100644 (file)
@@ -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,