diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 67 | 
1 files changed, 51 insertions, 16 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 49e4092f447f..28ec5f8ac1c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -50,6 +50,35 @@ to_amdgpu_device(struct amdgpu_vram_mgr *mgr)  	return container_of(mgr, struct amdgpu_device, mman.vram_mgr);  } +static inline struct drm_buddy_block * +amdgpu_vram_mgr_first_block(struct list_head *list) +{ +	return list_first_entry_or_null(list, struct drm_buddy_block, link); +} + +static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *head) +{ +	struct drm_buddy_block *block; +	u64 start, size; + +	block = amdgpu_vram_mgr_first_block(head); +	if (!block) +		return false; + +	while (head != block->link.next) { +		start = amdgpu_vram_mgr_block_start(block); +		size = amdgpu_vram_mgr_block_size(block); + +		block = list_entry(block->link.next, struct drm_buddy_block, link); +		if (start + size != amdgpu_vram_mgr_block_start(block)) +			return false; +	} + +	return true; +} + + +  /**   * DOC: mem_info_vram_total   * @@ -366,11 +395,11 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,  	unsigned long pages_per_block;  	int r; -	lpfn = place->lpfn << PAGE_SHIFT; +	lpfn = (u64)place->lpfn << PAGE_SHIFT;  	if (!lpfn)  		lpfn = man->size; -	fpfn = place->fpfn << PAGE_SHIFT; +	fpfn = (u64)place->fpfn << PAGE_SHIFT;  	max_bytes = adev->gmc.mc_vram_size;  	if (tbo->type != ttm_bo_type_kernel) @@ -410,12 +439,12 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,  		/* Allocate blocks in desired range */  		vres->flags |= DRM_BUDDY_RANGE_ALLOCATION; -	remaining_size = vres->base.num_pages << PAGE_SHIFT; +	remaining_size = (u64)vres->base.num_pages << PAGE_SHIFT;  	mutex_lock(&mgr->lock);  	while (remaining_size) {  		if (tbo->page_alignment) -			min_block_size = tbo->page_alignment << PAGE_SHIFT; +			min_block_size = (u64)tbo->page_alignment << PAGE_SHIFT;  		else  			min_block_size = mgr->default_page_size; @@ -424,12 +453,12 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,  		/* Limit maximum size to 2GiB due to SG table limitations */  		size = min(remaining_size, 2ULL << 30); -		if (size >= pages_per_block << PAGE_SHIFT) -			min_block_size = pages_per_block << PAGE_SHIFT; +		if (size >= (u64)pages_per_block << PAGE_SHIFT) +			min_block_size = (u64)pages_per_block << PAGE_SHIFT;  		cur_size = size; -		if (fpfn + size != place->lpfn << PAGE_SHIFT) { +		if (fpfn + size != (u64)place->lpfn << PAGE_SHIFT) {  			/*  			 * Except for actual range allocation, modify the size and  			 * min_block_size conforming to continuous flag enablement @@ -469,7 +498,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,  		LIST_HEAD(temp);  		trim_list = &vres->blocks; -		original_size = vres->base.num_pages << PAGE_SHIFT; +		original_size = (u64)vres->base.num_pages << PAGE_SHIFT;  		/*  		 * If size value is rounded up to min_block_size, trim the last @@ -496,16 +525,22 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,  			list_splice_tail(trim_list, &vres->blocks);  	} -	list_for_each_entry(block, &vres->blocks, link) -		vis_usage += amdgpu_vram_mgr_vis_size(adev, block); +	vres->base.start = 0; +	list_for_each_entry(block, &vres->blocks, link) { +		unsigned long start; -	block = amdgpu_vram_mgr_first_block(&vres->blocks); -	if (!block) { -		r = -EINVAL; -		goto error_fini; -	} +		start = amdgpu_vram_mgr_block_start(block) + +			amdgpu_vram_mgr_block_size(block); +		start >>= PAGE_SHIFT; + +		if (start > vres->base.num_pages) +			start -= vres->base.num_pages; +		else +			start = 0; +		vres->base.start = max(vres->base.start, start); -	vres->base.start = amdgpu_vram_mgr_block_start(block) >> PAGE_SHIFT; +		vis_usage += amdgpu_vram_mgr_vis_size(adev, block); +	}  	if (amdgpu_is_vram_mgr_blocks_contiguous(&vres->blocks))  		vres->base.placement |= TTM_PL_FLAG_CONTIGUOUS;  | 
