summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/drmP.h16
-rw-r--r--linux-core/drm_bo.c62
-rw-r--r--linux-core/drm_bo_move.c119
-rw-r--r--linux-core/i915_buffer.c34
4 files changed, 177 insertions, 54 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 55035210..86dcd79f 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -1509,6 +1509,15 @@ extern int drm_fence_buffer_objects(drm_file_t * priv,
uint32_t fence_flags,
drm_fence_object_t *fence,
drm_fence_object_t **used_fence);
+extern void drm_bo_add_to_lru(drm_buffer_object_t * bo,
+ drm_buffer_manager_t * bm);
+extern int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
+ int no_wait);
+extern int drm_bo_mem_space(drm_device_t *dev,
+ drm_bo_mem_reg_t *mem,
+ int no_wait);
+
+
/*
* Buffer object memory move helpers.
* drm_bo_move.c
@@ -1522,6 +1531,13 @@ extern int drm_bo_move_memcpy(drm_buffer_object_t *bo,
int evict,
int no_wait,
drm_bo_mem_reg_t *new_mem);
+extern int drm_bo_move_accel_cleanup(drm_buffer_object_t *bo,
+ int evict,
+ int no_wait,
+ uint32_t fence_type,
+ uint32_t fence_flags,
+ drm_bo_mem_reg_t *new_mem);
+
extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev);
extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index e3ecaf45..67e7d37f 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -56,8 +56,6 @@ static void drm_bo_destroy_locked(drm_buffer_object_t *bo);
static int drm_bo_setup_vm_locked(drm_buffer_object_t *bo);
static void drm_bo_takedown_vm_locked(drm_buffer_object_t *bo);
static void drm_bo_unmap_virtual(drm_buffer_object_t *bo);
-static int drm_bo_mem_space(drm_device_t *dev, drm_bo_mem_reg_t *mem,
- int no_wait);
static inline uint32_t drm_bo_type_flags(unsigned type)
{
@@ -68,8 +66,8 @@ static inline uint32_t drm_bo_type_flags(unsigned type)
* bo locked. dev->struct_mutex locked.
*/
-static void drm_bo_add_to_lru(drm_buffer_object_t * bo,
- drm_buffer_manager_t * bm)
+void drm_bo_add_to_lru(drm_buffer_object_t * bo,
+ drm_buffer_manager_t * bm)
{
struct list_head *list;
drm_mem_type_manager_t *man;
@@ -206,8 +204,8 @@ static int drm_bo_handle_move_mem(drm_buffer_object_t *bo,
* Wait until the buffer is idle.
*/
-static int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
- int no_wait)
+int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
+ int no_wait)
{
drm_fence_object_t *fence = bo->fence;
@@ -697,9 +695,9 @@ static int drm_bo_mt_compatible(drm_mem_type_manager_t *man,
}
-static int drm_bo_mem_space(drm_device_t *dev,
- drm_bo_mem_reg_t *mem,
- int no_wait)
+int drm_bo_mem_space(drm_device_t *dev,
+ drm_bo_mem_reg_t *mem,
+ int no_wait)
{
drm_buffer_manager_t *bm= &dev->bm;
drm_mem_type_manager_t *man;
@@ -777,6 +775,8 @@ static int drm_bo_mem_space(drm_device_t *dev,
ret = (has_eagain) ? -EAGAIN : -ENOMEM;
return ret;
}
+EXPORT_SYMBOL(drm_bo_mem_space);
+
static int drm_bo_new_mask(drm_buffer_object_t *bo,
uint32_t new_mask, uint32_t hint)
@@ -1439,50 +1439,6 @@ static int drm_bo_handle_wait(drm_file_t * priv, uint32_t handle,
return ret;
}
-/*
- * Transfer a buffer object's memory and LRU status to a newly
- * created object. User-space references remains with the old
- * object. Call bo->mutex locked.
- */
-
-int drm_buffer_object_transfer(drm_buffer_object_t *bo,
- drm_buffer_object_t **new_obj)
-{
- drm_buffer_object_t *fbo;
- drm_device_t *dev = bo->dev;
- drm_buffer_manager_t *bm = &dev->bm;
-
- fbo = drm_ctl_calloc(1, sizeof(*bo), DRM_MEM_BUFOBJ);
- if (!fbo)
- return -ENOMEM;
-
- *fbo = *bo;
- mutex_init(&fbo->mutex);
- mutex_lock(&fbo->mutex);
- mutex_lock(&dev->struct_mutex);
-
- INIT_LIST_HEAD(&fbo->ddestroy);
- INIT_LIST_HEAD(&fbo->lru);
- list_splice_init(&bo->lru, &fbo->lru);
-
- bo->mem.mm_node = NULL;
- bo->ttm = NULL;
- bo->fence = NULL;
- bo->mem.flags = 0;
-
- fbo->mem.mm_node->private = (void *)fbo;
- atomic_set(&fbo->usage, 1);
- atomic_inc(&bm->count);
- mutex_unlock(&dev->struct_mutex);
- mutex_unlock(&fbo->mutex);
-
- *new_obj = fbo;
- return 0;
-}
-
-
-
-
int drm_buffer_object_create(drm_file_t * priv,
unsigned long size,
drm_bo_type_t type,
diff --git a/linux-core/drm_bo_move.c b/linux-core/drm_bo_move.c
index 9bfb3ef1..d2c44501 100644
--- a/linux-core/drm_bo_move.c
+++ b/linux-core/drm_bo_move.c
@@ -73,6 +73,7 @@ int drm_bo_move_ttm(drm_buffer_object_t *bo,
DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE);
return 0;
}
+EXPORT_SYMBOL(drm_bo_move_ttm);
/**
@@ -267,3 +268,121 @@ out:
drm_mem_reg_iounmap(dev, &old_copy, old_iomap);
return ret;
}
+EXPORT_SYMBOL(drm_bo_move_memcpy);
+
+/*
+ * Transfer a buffer object's memory and LRU status to a newly
+ * created object. User-space references remains with the old
+ * object. Call bo->mutex locked.
+ */
+
+int drm_buffer_object_transfer(drm_buffer_object_t *bo,
+ drm_buffer_object_t **new_obj)
+{
+ drm_buffer_object_t *fbo;
+ drm_device_t *dev = bo->dev;
+ drm_buffer_manager_t *bm = &dev->bm;
+
+ fbo = drm_ctl_calloc(1, sizeof(*bo), DRM_MEM_BUFOBJ);
+ if (!fbo)
+ return -ENOMEM;
+
+ *fbo = *bo;
+ mutex_init(&fbo->mutex);
+ mutex_lock(&fbo->mutex);
+ mutex_lock(&dev->struct_mutex);
+
+ INIT_LIST_HEAD(&fbo->ddestroy);
+ INIT_LIST_HEAD(&fbo->lru);
+
+ bo->mem.mm_node = NULL;
+ bo->ttm = NULL;
+ atomic_inc(&bo->fence->usage);
+ bo->mem.flags = 0;
+
+ fbo->mem.mm_node->private = (void *)fbo;
+ atomic_set(&fbo->usage, 1);
+ atomic_inc(&bm->count);
+ mutex_unlock(&dev->struct_mutex);
+ mutex_unlock(&fbo->mutex);
+
+ *new_obj = fbo;
+ return 0;
+}
+
+int drm_bo_move_accel_cleanup(drm_buffer_object_t *bo,
+ int evict,
+ int no_wait,
+ uint32_t fence_type,
+ uint32_t fence_flags,
+ drm_bo_mem_reg_t *new_mem)
+{
+ drm_device_t *dev = bo->dev;
+ drm_mem_type_manager_t *man = &dev->bm.man[new_mem->mem_type];
+ drm_bo_mem_reg_t *old_mem = &bo->mem;
+ int ret;
+ uint32_t save_flags = old_mem->flags;
+ uint32_t save_mask = old_mem->mask;
+ drm_buffer_object_t *old_obj;
+
+ if (bo->fence)
+ drm_fence_usage_deref_unlocked(dev, bo->fence);
+
+ ret = drm_fence_object_create(dev, fence_type,
+ fence_flags | DRM_FENCE_FLAG_EMIT,
+ &bo->fence);
+ if (ret)
+ return ret;
+
+ if (evict) {
+ ret = drm_bo_wait(bo, 0, 1, 0);
+ if (ret)
+ return ret;
+ if (old_mem->mm_node) {
+ mutex_lock(&dev->struct_mutex);
+ drm_mm_put_block(old_mem->mm_node);
+ old_mem->mm_node = NULL;
+ mutex_unlock(&dev->struct_mutex);
+ }
+ if ((man->flags & _DRM_FLAG_MEMTYPE_FIXED) &&
+ (bo->ttm != NULL)) {
+ drm_ttm_unbind(bo->ttm);
+ drm_destroy_ttm(bo->ttm);
+ bo->ttm = NULL;
+ }
+ } else {
+
+ /* This should help pipeline ordinary buffer moves.
+ *
+ * Hang old buffer memory on a new buffer object,
+ * and leave it to be released when the blit
+ * operation has completed.
+ */
+
+ ret = drm_buffer_object_transfer(bo, &old_obj);
+ if (ret)
+ return ret;
+
+ if (!(man->flags & _DRM_FLAG_MEMTYPE_FIXED))
+ old_obj->ttm = NULL;
+ else
+ bo->ttm = NULL;
+
+ atomic_inc(&old_obj->fence->usage);
+ mutex_lock(&dev->struct_mutex);
+ list_del(&old_obj->lru);
+ drm_bo_add_to_lru(old_obj, &old_obj->dev->bm);
+ drm_bo_usage_deref_locked(old_obj);
+ mutex_unlock(&dev->struct_mutex);
+
+ }
+
+ *old_mem = *new_mem;
+ new_mem->mm_node = NULL;
+ old_mem->mask = save_mask;
+ DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE);
+ return 0;
+}
+EXPORT_SYMBOL(drm_bo_move_accel_cleanup);
+
+
diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c
index 5d1c39be..41f05b78 100644
--- a/linux-core/i915_buffer.c
+++ b/linux-core/i915_buffer.c
@@ -118,7 +118,7 @@ uint32_t i915_evict_flags(drm_device_t *dev, uint32_t type)
}
}
-void i915_emit_copy_blit(drm_device_t *dev,
+static void i915_emit_copy_blit(drm_device_t *dev,
uint32_t src_offset,
uint32_t dst_offset,
uint32_t pages,
@@ -161,3 +161,35 @@ void i915_emit_copy_blit(drm_device_t *dev,
}
return;
}
+
+static int drm_bo_move_blit(drm_buffer_object_t *bo,
+ int evict,
+ int no_wait,
+ drm_bo_mem_reg_t *new_mem)
+{
+ drm_bo_mem_reg_t *old_mem = &bo->mem;
+ int dir = 0;
+
+ if ((old_mem->mem_type == new_mem->mem_type) &&
+ (new_mem->mm_node->start <
+ old_mem->mm_node->start + old_mem->mm_node->size)) {
+ dir = 1;
+ }
+
+ i915_emit_copy_blit(bo->dev,
+ old_mem->mm_node->start << PAGE_SHIFT,
+ new_mem->mm_node->start << PAGE_SHIFT,
+ new_mem->num_pages,
+ dir);
+
+ i915_emit_mi_flush(bo->dev, MI_READ_FLUSH | MI_EXE_FLUSH);
+
+ return drm_bo_move_accel_cleanup(bo, evict, no_wait,
+ DRM_FENCE_TYPE_EXE |
+ DRM_I915_FENCE_TYPE_RW,
+ DRM_I915_FENCE_FLAG_FLUSHED,
+ new_mem);
+}
+
+
+