Add an accelerated buffer copy cleanup helper.
Export helper functions and make some important buffer-object functions non-static. Add an i915 accelerated blit buffer move for pci memory buffers.main
parent
a0ed808d05
commit
b2bcbf874b
|
@ -1509,6 +1509,15 @@ extern int drm_fence_buffer_objects(drm_file_t * priv,
|
||||||
uint32_t fence_flags,
|
uint32_t fence_flags,
|
||||||
drm_fence_object_t *fence,
|
drm_fence_object_t *fence,
|
||||||
drm_fence_object_t **used_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.
|
* Buffer object memory move helpers.
|
||||||
* drm_bo_move.c
|
* drm_bo_move.c
|
||||||
|
@ -1522,6 +1531,13 @@ extern int drm_bo_move_memcpy(drm_buffer_object_t *bo,
|
||||||
int evict,
|
int evict,
|
||||||
int no_wait,
|
int no_wait,
|
||||||
drm_bo_mem_reg_t *new_mem);
|
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_ioremap(struct drm_map *map, struct drm_device *dev);
|
||||||
extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
|
extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev);
|
||||||
|
|
||||||
|
|
|
@ -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 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_takedown_vm_locked(drm_buffer_object_t *bo);
|
||||||
static void drm_bo_unmap_virtual(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)
|
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.
|
* bo locked. dev->struct_mutex locked.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void drm_bo_add_to_lru(drm_buffer_object_t * bo,
|
void drm_bo_add_to_lru(drm_buffer_object_t * bo,
|
||||||
drm_buffer_manager_t * bm)
|
drm_buffer_manager_t * bm)
|
||||||
{
|
{
|
||||||
struct list_head *list;
|
struct list_head *list;
|
||||||
drm_mem_type_manager_t *man;
|
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.
|
* Wait until the buffer is idle.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
|
int drm_bo_wait(drm_buffer_object_t * bo, int lazy, int ignore_signals,
|
||||||
int no_wait)
|
int no_wait)
|
||||||
{
|
{
|
||||||
|
|
||||||
drm_fence_object_t *fence = bo->fence;
|
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,
|
int drm_bo_mem_space(drm_device_t *dev,
|
||||||
drm_bo_mem_reg_t *mem,
|
drm_bo_mem_reg_t *mem,
|
||||||
int no_wait)
|
int no_wait)
|
||||||
{
|
{
|
||||||
drm_buffer_manager_t *bm= &dev->bm;
|
drm_buffer_manager_t *bm= &dev->bm;
|
||||||
drm_mem_type_manager_t *man;
|
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;
|
ret = (has_eagain) ? -EAGAIN : -ENOMEM;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(drm_bo_mem_space);
|
||||||
|
|
||||||
|
|
||||||
static int drm_bo_new_mask(drm_buffer_object_t *bo,
|
static int drm_bo_new_mask(drm_buffer_object_t *bo,
|
||||||
uint32_t new_mask, uint32_t hint)
|
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;
|
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,
|
int drm_buffer_object_create(drm_file_t * priv,
|
||||||
unsigned long size,
|
unsigned long size,
|
||||||
drm_bo_type_t type,
|
drm_bo_type_t type,
|
||||||
|
|
|
@ -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);
|
DRM_FLAG_MASKED(save_flags, new_mem->flags, DRM_BO_MASK_MEMTYPE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(drm_bo_move_ttm);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -267,3 +268,121 @@ out:
|
||||||
drm_mem_reg_iounmap(dev, &old_copy, old_iomap);
|
drm_mem_reg_iounmap(dev, &old_copy, old_iomap);
|
||||||
return ret;
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 src_offset,
|
||||||
uint32_t dst_offset,
|
uint32_t dst_offset,
|
||||||
uint32_t pages,
|
uint32_t pages,
|
||||||
|
@ -161,3 +161,35 @@ void i915_emit_copy_blit(drm_device_t *dev,
|
||||||
}
|
}
|
||||||
return;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue