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,
|
||||
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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue