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); +} + + +