diff options
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_bo.c')
| -rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo.c | 190 | 
1 files changed, 69 insertions, 121 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 98819462f025..8d91b0428af1 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -51,6 +51,7 @@ static void ttm_bo_global_kobj_release(struct kobject *kobj);  DEFINE_MUTEX(ttm_global_mutex);  unsigned ttm_bo_glob_use_count;  struct ttm_bo_global ttm_bo_glob; +EXPORT_SYMBOL(ttm_bo_glob);  static struct attribute ttm_bo_count = {  	.name = "bo_count", @@ -148,23 +149,21 @@ static void ttm_bo_release_list(struct kref *list_kref)  {  	struct ttm_buffer_object *bo =  	    container_of(list_kref, struct ttm_buffer_object, list_kref); -	struct ttm_bo_device *bdev = bo->bdev;  	size_t acc_size = bo->acc_size;  	BUG_ON(kref_read(&bo->list_kref));  	BUG_ON(kref_read(&bo->kref)); -	BUG_ON(atomic_read(&bo->cpu_writers));  	BUG_ON(bo->mem.mm_node != NULL);  	BUG_ON(!list_empty(&bo->lru));  	BUG_ON(!list_empty(&bo->ddestroy));  	ttm_tt_destroy(bo->ttm); -	atomic_dec(&bo->bdev->glob->bo_count); +	atomic_dec(&ttm_bo_glob.bo_count);  	dma_fence_put(bo->moving);  	if (!ttm_bo_uses_embedded_gem_object(bo))  		dma_resv_fini(&bo->base._resv);  	mutex_destroy(&bo->wu_mutex);  	bo->destroy(bo); -	ttm_mem_global_free(bdev->glob->mem_glob, acc_size); +	ttm_mem_global_free(&ttm_mem_glob, acc_size);  }  static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo, @@ -188,23 +187,17 @@ static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo,  	if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED) && bo->ttm &&  	    !(bo->ttm->page_flags & (TTM_PAGE_FLAG_SG |  				     TTM_PAGE_FLAG_SWAPPED))) { -		list_add_tail(&bo->swap, &bdev->glob->swap_lru[bo->priority]); +		list_add_tail(&bo->swap, &ttm_bo_glob.swap_lru[bo->priority]);  		kref_get(&bo->list_kref);  	}  } -void ttm_bo_add_to_lru(struct ttm_buffer_object *bo) -{ -	ttm_bo_add_mem_to_lru(bo, &bo->mem); -} -EXPORT_SYMBOL(ttm_bo_add_to_lru); -  static void ttm_bo_ref_bug(struct kref *list_kref)  {  	BUG();  } -void ttm_bo_del_from_lru(struct ttm_buffer_object *bo) +static void ttm_bo_del_from_lru(struct ttm_buffer_object *bo)  {  	struct ttm_bo_device *bdev = bo->bdev;  	bool notify = false; @@ -224,16 +217,6 @@ void ttm_bo_del_from_lru(struct ttm_buffer_object *bo)  		bdev->driver->del_from_lru_notify(bo);  } -void ttm_bo_del_sub_from_lru(struct ttm_buffer_object *bo) -{ -	struct ttm_bo_global *glob = bo->bdev->glob; - -	spin_lock(&glob->lru_lock); -	ttm_bo_del_from_lru(bo); -	spin_unlock(&glob->lru_lock); -} -EXPORT_SYMBOL(ttm_bo_del_sub_from_lru); -  static void ttm_bo_bulk_move_set_pos(struct ttm_lru_bulk_move_pos *pos,  				     struct ttm_buffer_object *bo)  { @@ -248,7 +231,7 @@ void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo,  	dma_resv_assert_held(bo->base.resv);  	ttm_bo_del_from_lru(bo); -	ttm_bo_add_to_lru(bo); +	ttm_bo_add_mem_to_lru(bo, &bo->mem);  	if (bulk && !(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {  		switch (bo->mem.mem_type) { @@ -311,7 +294,7 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk)  		dma_resv_assert_held(pos->first->base.resv);  		dma_resv_assert_held(pos->last->base.resv); -		lru = &pos->first->bdev->glob->swap_lru[i]; +		lru = &ttm_bo_glob.swap_lru[i];  		list_bulk_move_tail(lru, &pos->first->swap, &pos->last->swap);  	}  } @@ -475,7 +458,6 @@ static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)  static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)  {  	struct ttm_bo_device *bdev = bo->bdev; -	struct ttm_bo_global *glob = bdev->glob;  	int ret;  	ret = ttm_bo_individualize_resv(bo); @@ -485,16 +467,16 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)  		 */  		dma_resv_wait_timeout_rcu(bo->base.resv, true, false,  						    30 * HZ); -		spin_lock(&glob->lru_lock); +		spin_lock(&ttm_bo_glob.lru_lock);  		goto error;  	} -	spin_lock(&glob->lru_lock); +	spin_lock(&ttm_bo_glob.lru_lock);  	ret = dma_resv_trylock(bo->base.resv) ? 0 : -EBUSY;  	if (!ret) {  		if (dma_resv_test_signaled_rcu(&bo->base._resv, true)) {  			ttm_bo_del_from_lru(bo); -			spin_unlock(&glob->lru_lock); +			spin_unlock(&ttm_bo_glob.lru_lock);  			if (bo->base.resv != &bo->base._resv)  				dma_resv_unlock(&bo->base._resv); @@ -512,7 +494,7 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)  		 */  		if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT) {  			bo->mem.placement &= ~TTM_PL_FLAG_NO_EVICT; -			ttm_bo_add_to_lru(bo); +			ttm_bo_move_to_lru_tail(bo, NULL);  		}  		dma_resv_unlock(bo->base.resv); @@ -523,7 +505,7 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)  error:  	kref_get(&bo->list_kref);  	list_add_tail(&bo->ddestroy, &bdev->ddestroy); -	spin_unlock(&glob->lru_lock); +	spin_unlock(&ttm_bo_glob.lru_lock);  	schedule_delayed_work(&bdev->wq,  			      ((HZ / 100) < 1) ? 1 : HZ / 100); @@ -546,7 +528,6 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,  			       bool interruptible, bool no_wait_gpu,  			       bool unlock_resv)  { -	struct ttm_bo_global *glob = bo->bdev->glob;  	struct dma_resv *resv;  	int ret; @@ -565,7 +546,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,  		if (unlock_resv)  			dma_resv_unlock(bo->base.resv); -		spin_unlock(&glob->lru_lock); +		spin_unlock(&ttm_bo_glob.lru_lock);  		lret = dma_resv_wait_timeout_rcu(resv, true,  							   interruptible, @@ -576,7 +557,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,  		else if (lret == 0)  			return -EBUSY; -		spin_lock(&glob->lru_lock); +		spin_lock(&ttm_bo_glob.lru_lock);  		if (unlock_resv && !dma_resv_trylock(bo->base.resv)) {  			/*  			 * We raced, and lost, someone else holds the reservation now, @@ -586,7 +567,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,  			 * delayed destruction would succeed, so just return success  			 * here.  			 */ -			spin_unlock(&glob->lru_lock); +			spin_unlock(&ttm_bo_glob.lru_lock);  			return 0;  		}  		ret = 0; @@ -595,7 +576,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,  	if (ret || unlikely(list_empty(&bo->ddestroy))) {  		if (unlock_resv)  			dma_resv_unlock(bo->base.resv); -		spin_unlock(&glob->lru_lock); +		spin_unlock(&ttm_bo_glob.lru_lock);  		return ret;  	} @@ -603,7 +584,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,  	list_del_init(&bo->ddestroy);  	kref_put(&bo->list_kref, ttm_bo_ref_bug); -	spin_unlock(&glob->lru_lock); +	spin_unlock(&ttm_bo_glob.lru_lock);  	ttm_bo_cleanup_memtype_use(bo);  	if (unlock_resv) @@ -618,7 +599,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,   */  static bool ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)  { -	struct ttm_bo_global *glob = bdev->glob; +	struct ttm_bo_global *glob = &ttm_bo_glob;  	struct list_head removed;  	bool empty; @@ -676,7 +657,7 @@ static void ttm_bo_release(struct kref *kref)  	if (bo->bdev->driver->release_notify)  		bo->bdev->driver->release_notify(bo); -	drm_vma_offset_remove(&bdev->vma_manager, &bo->base.vma_node); +	drm_vma_offset_remove(bdev->vma_manager, &bo->base.vma_node);  	ttm_mem_io_lock(man, false);  	ttm_mem_io_free_vm(bo);  	ttm_mem_io_unlock(man); @@ -842,13 +823,12 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,  			       struct ww_acquire_ctx *ticket)  {  	struct ttm_buffer_object *bo = NULL, *busy_bo = NULL; -	struct ttm_bo_global *glob = bdev->glob;  	struct ttm_mem_type_manager *man = &bdev->man[mem_type];  	bool locked = false;  	unsigned i;  	int ret; -	spin_lock(&glob->lru_lock); +	spin_lock(&ttm_bo_glob.lru_lock);  	for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) {  		list_for_each_entry(bo, &man->lru[i], lru) {  			bool busy; @@ -880,7 +860,7 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,  	if (!bo) {  		if (busy_bo)  			kref_get(&busy_bo->list_kref); -		spin_unlock(&glob->lru_lock); +		spin_unlock(&ttm_bo_glob.lru_lock);  		ret = ttm_mem_evict_wait_busy(busy_bo, ctx, ticket);  		if (busy_bo)  			kref_put(&busy_bo->list_kref, ttm_bo_release_list); @@ -896,17 +876,11 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev,  		return ret;  	} -	ttm_bo_del_from_lru(bo); -	spin_unlock(&glob->lru_lock); +	spin_unlock(&ttm_bo_glob.lru_lock);  	ret = ttm_bo_evict(bo, ctx); -	if (locked) { +	if (locked)  		ttm_bo_unreserve(bo); -	} else { -		spin_lock(&glob->lru_lock); -		ttm_bo_add_to_lru(bo); -		spin_unlock(&glob->lru_lock); -	}  	kref_put(&bo->list_kref, ttm_bo_release_list);  	return ret; @@ -926,7 +900,8 @@ EXPORT_SYMBOL(ttm_bo_mem_put);   */  static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,  				 struct ttm_mem_type_manager *man, -				 struct ttm_mem_reg *mem) +				 struct ttm_mem_reg *mem, +				 bool no_wait_gpu)  {  	struct dma_fence *fence;  	int ret; @@ -935,19 +910,22 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,  	fence = dma_fence_get(man->move);  	spin_unlock(&man->move_lock); -	if (fence) { -		dma_resv_add_shared_fence(bo->base.resv, fence); +	if (!fence) +		return 0; -		ret = dma_resv_reserve_shared(bo->base.resv, 1); -		if (unlikely(ret)) { -			dma_fence_put(fence); -			return ret; -		} +	if (no_wait_gpu) +		return -EBUSY; -		dma_fence_put(bo->moving); -		bo->moving = fence; +	dma_resv_add_shared_fence(bo->base.resv, fence); + +	ret = dma_resv_reserve_shared(bo->base.resv, 1); +	if (unlikely(ret)) { +		dma_fence_put(fence); +		return ret;  	} +	dma_fence_put(bo->moving); +	bo->moving = fence;  	return 0;  } @@ -978,7 +956,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,  			return ret;  	} while (1); -	return ttm_bo_add_move_fence(bo, man, mem); +	return ttm_bo_add_move_fence(bo, man, mem, ctx->no_wait_gpu);  }  static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man, @@ -1068,12 +1046,10 @@ static int ttm_bo_mem_placement(struct ttm_buffer_object *bo,  	mem->mem_type = mem_type;  	mem->placement = cur_flags; -	if (bo->mem.mem_type < mem_type && !list_empty(&bo->lru)) { -		spin_lock(&bo->bdev->glob->lru_lock); -		ttm_bo_del_from_lru(bo); -		ttm_bo_add_mem_to_lru(bo, mem); -		spin_unlock(&bo->bdev->glob->lru_lock); -	} +	spin_lock(&ttm_bo_glob.lru_lock); +	ttm_bo_del_from_lru(bo); +	ttm_bo_add_mem_to_lru(bo, mem); +	spin_unlock(&ttm_bo_glob.lru_lock);  	return 0;  } @@ -1120,14 +1096,18 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,  		if (unlikely(ret))  			goto error; -		if (mem->mm_node) { -			ret = ttm_bo_add_move_fence(bo, man, mem); -			if (unlikely(ret)) { -				(*man->func->put_node)(man, mem); -				goto error; -			} -			return 0; +		if (!mem->mm_node) +			continue; + +		ret = ttm_bo_add_move_fence(bo, man, mem, ctx->no_wait_gpu); +		if (unlikely(ret)) { +			(*man->func->put_node)(man, mem); +			if (ret == -EBUSY) +				continue; + +			goto error;  		} +		return 0;  	}  	for (i = 0; i < placement->num_busy_placement; ++i) { @@ -1160,9 +1140,9 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,  error:  	if (bo->mem.mem_type == TTM_PL_SYSTEM && !list_empty(&bo->lru)) { -		spin_lock(&bo->bdev->glob->lru_lock); +		spin_lock(&ttm_bo_glob.lru_lock);  		ttm_bo_move_to_lru_tail(bo, NULL); -		spin_unlock(&bo->bdev->glob->lru_lock); +		spin_unlock(&ttm_bo_glob.lru_lock);  	}  	return ret; @@ -1286,9 +1266,9 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,  			 struct dma_resv *resv,  			 void (*destroy) (struct ttm_buffer_object *))  { +	struct ttm_mem_global *mem_glob = &ttm_mem_glob;  	int ret = 0;  	unsigned long num_pages; -	struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;  	bool locked;  	ret = ttm_mem_global_alloc(mem_glob, acc_size, ctx); @@ -1315,7 +1295,6 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,  	kref_init(&bo->kref);  	kref_init(&bo->list_kref); -	atomic_set(&bo->cpu_writers, 0);  	INIT_LIST_HEAD(&bo->lru);  	INIT_LIST_HEAD(&bo->ddestroy);  	INIT_LIST_HEAD(&bo->swap); @@ -1349,7 +1328,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,  		dma_resv_init(&bo->base._resv);  		drm_vma_node_reset(&bo->base.vma_node);  	} -	atomic_inc(&bo->bdev->glob->bo_count); +	atomic_inc(&ttm_bo_glob.bo_count);  	/*  	 * For ttm_bo_type_device buffers, allocate @@ -1357,7 +1336,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,  	 */  	if (bo->type == ttm_bo_type_device ||  	    bo->type == ttm_bo_type_sg) -		ret = drm_vma_offset_add(&bdev->vma_manager, &bo->base.vma_node, +		ret = drm_vma_offset_add(bdev->vma_manager, &bo->base.vma_node,  					 bo->mem.num_pages);  	/* passed reservation objects should already be locked, @@ -1379,11 +1358,9 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,  		return ret;  	} -	if (resv && !(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) { -		spin_lock(&bdev->glob->lru_lock); -		ttm_bo_add_to_lru(bo); -		spin_unlock(&bdev->glob->lru_lock); -	} +	spin_lock(&ttm_bo_glob.lru_lock); +	ttm_bo_move_to_lru_tail(bo, NULL); +	spin_unlock(&ttm_bo_glob.lru_lock);  	return ret;  } @@ -1481,7 +1458,7 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,  		.flags = TTM_OPT_FLAG_FORCE_ALLOC  	};  	struct ttm_mem_type_manager *man = &bdev->man[mem_type]; -	struct ttm_bo_global *glob = bdev->glob; +	struct ttm_bo_global *glob = &ttm_bo_glob;  	struct dma_fence *fence;  	int ret;  	unsigned i; @@ -1650,8 +1627,6 @@ static int ttm_bo_global_init(void)  		goto out;  	spin_lock_init(&glob->lru_lock); -	glob->mem_glob = &ttm_mem_glob; -	glob->mem_glob->bo_glob = glob;  	glob->dummy_read_page = alloc_page(__GFP_ZERO | GFP_DMA32);  	if (unlikely(glob->dummy_read_page == NULL)) { @@ -1675,10 +1650,10 @@ out:  int ttm_bo_device_release(struct ttm_bo_device *bdev)  { +	struct ttm_bo_global *glob = &ttm_bo_glob;  	int ret = 0;  	unsigned i = TTM_NUM_MEM_TYPES;  	struct ttm_mem_type_manager *man; -	struct ttm_bo_global *glob = bdev->glob;  	while (i--) {  		man = &bdev->man[i]; @@ -1708,8 +1683,6 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev)  			pr_debug("Swap list %d was clean\n", i);  	spin_unlock(&glob->lru_lock); -	drm_vma_offset_manager_destroy(&bdev->vma_manager); -  	if (!ret)  		ttm_bo_global_release(); @@ -1720,11 +1693,15 @@ EXPORT_SYMBOL(ttm_bo_device_release);  int ttm_bo_device_init(struct ttm_bo_device *bdev,  		       struct ttm_bo_driver *driver,  		       struct address_space *mapping, +		       struct drm_vma_offset_manager *vma_manager,  		       bool need_dma32)  {  	struct ttm_bo_global *glob = &ttm_bo_glob;  	int ret; +	if (WARN_ON(vma_manager == NULL)) +		return -EINVAL; +  	ret = ttm_bo_global_init();  	if (ret)  		return ret; @@ -1741,13 +1718,10 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev,  	if (unlikely(ret != 0))  		goto out_no_sys; -	drm_vma_offset_manager_init(&bdev->vma_manager, -				    DRM_FILE_PAGE_OFFSET_START, -				    DRM_FILE_PAGE_OFFSET_SIZE); +	bdev->vma_manager = vma_manager;  	INIT_DELAYED_WORK(&bdev->wq, ttm_bo_delayed_workqueue);  	INIT_LIST_HEAD(&bdev->ddestroy);  	bdev->dev_mapping = mapping; -	bdev->glob = glob;  	bdev->need_dma32 = need_dma32;  	mutex_lock(&ttm_global_mutex);  	list_add_tail(&bdev->device_list, &glob->device_list); @@ -1827,31 +1801,6 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,  }  EXPORT_SYMBOL(ttm_bo_wait); -int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait) -{ -	int ret = 0; - -	/* -	 * Using ttm_bo_reserve makes sure the lru lists are updated. -	 */ - -	ret = ttm_bo_reserve(bo, true, no_wait, NULL); -	if (unlikely(ret != 0)) -		return ret; -	ret = ttm_bo_wait(bo, true, no_wait); -	if (likely(ret == 0)) -		atomic_inc(&bo->cpu_writers); -	ttm_bo_unreserve(bo); -	return ret; -} -EXPORT_SYMBOL(ttm_bo_synccpu_write_grab); - -void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo) -{ -	atomic_dec(&bo->cpu_writers); -} -EXPORT_SYMBOL(ttm_bo_synccpu_write_release); -  /**   * A buffer object shrink method that tries to swap out the first   * buffer object on the bo_global::swap_lru list. @@ -1951,8 +1900,7 @@ void ttm_bo_swapout_all(struct ttm_bo_device *bdev)  		.no_wait_gpu = false  	}; -	while (ttm_bo_swapout(bdev->glob, &ctx) == 0) -		; +	while (ttm_bo_swapout(&ttm_bo_glob, &ctx) == 0);  }  EXPORT_SYMBOL(ttm_bo_swapout_all);  |