On Wed, Jun 15, 2016 at 7:44 AM, Christian König <deathsimple@xxxxxxxxxxx> wrote: > From: Christian König <christian.koenig@xxxxxxx> > > Free up the memory immediately, remember the last eviction for each domain and > make new allocations depend on the last eviction to be completed. > > Signed-off-by: Christian König <christian.koenig@xxxxxxx> Minor typo in the patch title: s/infrastructur/infrastructure/ Alex > --- > drivers/gpu/drm/ttm/ttm_bo.c | 49 ++++++++++++++++++--- > drivers/gpu/drm/ttm/ttm_bo_util.c | 92 +++++++++++++++++++++++++++++++++++++++ > include/drm/ttm/ttm_bo_driver.h | 24 ++++++++++ > 3 files changed, 160 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c > index 28cd535..5d93169 100644 > --- a/drivers/gpu/drm/ttm/ttm_bo.c > +++ b/drivers/gpu/drm/ttm/ttm_bo.c > @@ -788,6 +788,34 @@ void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem) > EXPORT_SYMBOL(ttm_bo_mem_put); > > /** > + * Add the last move fence to the BO and reserve a new shared slot. > + */ > +static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo, > + struct ttm_mem_type_manager *man, > + struct ttm_mem_reg *mem) > +{ > + struct fence *fence; > + int ret; > + > + spin_lock(&man->move_lock); > + fence = fence_get(man->move); > + spin_unlock(&man->move_lock); > + > + if (fence) { > + reservation_object_add_shared_fence(bo->resv, fence); > + > + ret = reservation_object_reserve_shared(bo->resv); > + if (unlikely(ret)) > + return ret; > + > + fence_put(bo->moving); > + bo->moving = fence; > + } > + > + return 0; > +} > + > +/** > * Repeatedly evict memory from the LRU for @mem_type until we create enough > * space, or we've evicted everything and there isn't enough space. > */ > @@ -813,10 +841,8 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, > if (unlikely(ret != 0)) > return ret; > } while (1); > - if (mem->mm_node == NULL) > - return -ENOMEM; > mem->mem_type = mem_type; > - return 0; > + return ttm_bo_add_move_fence(bo, man, mem); > } > > static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man, > @@ -886,6 +912,10 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, > bool has_erestartsys = false; > int i, ret; > > + ret = reservation_object_reserve_shared(bo->resv); > + if (unlikely(ret)) > + return ret; > + > mem->mm_node = NULL; > for (i = 0; i < placement->num_placement; ++i) { > const struct ttm_place *place = &placement->placement[i]; > @@ -919,9 +949,15 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, > ret = (*man->func->get_node)(man, bo, place, mem); > if (unlikely(ret)) > return ret; > - > - if (mem->mm_node) > + > + if (mem->mm_node) { > + ret = ttm_bo_add_move_fence(bo, man, mem); > + if (unlikely(ret)) { > + (*man->func->put_node)(man, mem); > + return ret; > + } > break; > + } > } > > if ((type_ok && (mem_type == TTM_PL_SYSTEM)) || mem->mm_node) { > @@ -1290,6 +1326,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) > mem_type); > return ret; > } > + fence_put(man->move); > > man->use_type = false; > man->has_type = false; > @@ -1335,6 +1372,7 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, > man->io_reserve_fastpath = true; > man->use_io_reserve_lru = false; > mutex_init(&man->io_reserve_mutex); > + spin_lock_init(&man->move_lock); > INIT_LIST_HEAD(&man->io_reserve_lru); > > ret = bdev->driver->init_mem_type(bdev, type, man); > @@ -1353,6 +1391,7 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, > man->size = p_size; > > INIT_LIST_HEAD(&man->lru); > + man->move = NULL; > > return 0; > } > diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c > index 9ea8d02..0c389a5 100644 > --- a/drivers/gpu/drm/ttm/ttm_bo_util.c > +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c > @@ -696,3 +696,95 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, > return 0; > } > EXPORT_SYMBOL(ttm_bo_move_accel_cleanup); > + > +int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, > + struct fence *fence, bool evict, > + struct ttm_mem_reg *new_mem) > +{ > + struct ttm_bo_device *bdev = bo->bdev; > + struct ttm_mem_reg *old_mem = &bo->mem; > + > + struct ttm_mem_type_manager *from = &bdev->man[old_mem->mem_type]; > + struct ttm_mem_type_manager *to = &bdev->man[new_mem->mem_type]; > + > + int ret; > + > + reservation_object_add_excl_fence(bo->resv, fence); > + > + if (!evict) { > + struct ttm_buffer_object *ghost_obj; > + > + /** > + * This should help pipeline ordinary buffer moves. > + * > + * Hang old buffer memory on a new buffer object, > + * and leave it to be released when the GPU > + * operation has completed. > + */ > + > + fence_put(bo->moving); > + bo->moving = fence_get(fence); > + > + ret = ttm_buffer_object_transfer(bo, &ghost_obj); > + if (ret) > + return ret; > + > + reservation_object_add_excl_fence(ghost_obj->resv, fence); > + > + /** > + * If we're not moving to fixed memory, the TTM object > + * needs to stay alive. Otherwhise hang it on the ghost > + * bo to be unbound and destroyed. > + */ > + > + if (!(to->flags & TTM_MEMTYPE_FLAG_FIXED)) > + ghost_obj->ttm = NULL; > + else > + bo->ttm = NULL; > + > + ttm_bo_unreserve(ghost_obj); > + ttm_bo_unref(&ghost_obj); > + > + } else if (from->flags & TTM_MEMTYPE_FLAG_FIXED) { > + > + /** > + * BO doesn't have a TTM we need to bind/unbind. Just remember > + * this eviction and free up the allocation > + */ > + > + spin_lock(&from->move_lock); > + if (!from->move || fence_is_later(from->move, fence)) { > + fence_put(from->move); > + from->move = fence_get(fence); > + } > + spin_unlock(&from->move_lock); > + > + ttm_bo_free_old_node(bo); > + > + fence_put(bo->moving); > + bo->moving = fence_get(fence); > + > + } else { > + /** > + * Last resort, wait for the move to be completed. > + * > + * Should never happen in pratice. > + */ > + > + ret = ttm_bo_wait(bo, false, false); > + if (ret) > + return ret; > + > + if (to->flags & TTM_MEMTYPE_FLAG_FIXED) { > + ttm_tt_destroy(bo->ttm); > + bo->ttm = NULL; > + } > + ttm_bo_free_old_node(bo); > + } > + > + *old_mem = *new_mem; > + new_mem->mm_node = NULL; > + > + return 0; > +} > +EXPORT_SYMBOL(ttm_bo_pipeline_move); > diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h > index 44dea22..e2ebe66 100644 > --- a/include/drm/ttm/ttm_bo_driver.h > +++ b/include/drm/ttm/ttm_bo_driver.h > @@ -258,8 +258,10 @@ struct ttm_mem_type_manager_func { > * reserved by the TTM vm system. > * @io_reserve_lru: Optional lru list for unreserving io mem regions. > * @io_reserve_fastpath: Only use bdev::driver::io_mem_reserve to obtain > + * @move_lock: lock for move fence > * static information. bdev::driver::io_mem_free is never used. > * @lru: The lru list for this memory type. > + * @move: The fence of the last pipelined move operation. > * > * This structure is used to identify and manage memory types for a device. > * It's set up by the ttm_bo_driver::init_mem_type method. > @@ -286,6 +288,7 @@ struct ttm_mem_type_manager { > struct mutex io_reserve_mutex; > bool use_io_reserve_lru; > bool io_reserve_fastpath; > + spinlock_t move_lock; > > /* > * Protected by @io_reserve_mutex: > @@ -298,6 +301,11 @@ struct ttm_mem_type_manager { > */ > > struct list_head lru; > + > + /* > + * Protected by @move_lock. > + */ > + struct fence *move; > }; > > /** > @@ -1014,6 +1022,22 @@ extern void ttm_bo_free_old_node(struct ttm_buffer_object *bo); > extern int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, > struct fence *fence, bool evict, > struct ttm_mem_reg *new_mem); > + > +/** > + * ttm_bo_pipeline_move. > + * > + * @bo: A pointer to a struct ttm_buffer_object. > + * @fence: A fence object that signals when moving is complete. > + * @evict: This is an evict move. Don't return until the buffer is idle. > + * @new_mem: struct ttm_mem_reg indicating where to move. > + * > + * Function for pipelining accelerated moves. Either free the memory > + * immediately or hang it on a temporary buffer object. > + */ > +int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, > + struct fence *fence, bool evict, > + struct ttm_mem_reg *new_mem); > + > /** > * ttm_io_prot > * > -- > 2.5.0 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel