diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 32 | 
1 files changed, 18 insertions, 14 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 352b30409060..0877ff9a9594 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -181,7 +181,7 @@ static unsigned amdgpu_vm_num_entries(struct amdgpu_device *adev,  	if (level == adev->vm_manager.root_level)  		/* For the root directory */ -		return round_up(adev->vm_manager.max_pfn, 1 << shift) >> shift; +		return round_up(adev->vm_manager.max_pfn, 1ULL << shift) >> shift;  	else if (level != AMDGPU_VM_PTB)  		/* Everything in between */  		return 512; @@ -1632,13 +1632,6 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,  			continue;  		} -		/* First check if the entry is already handled */ -		if (cursor.pfn < frag_start) { -			cursor.entry->huge = true; -			amdgpu_vm_pt_next(adev, &cursor); -			continue; -		} -  		/* If it isn't already handled it can't be a huge page */  		if (cursor.entry->huge) {  			/* Add the entry to the relocated list to update it. */ @@ -1663,9 +1656,11 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,  			if (!amdgpu_vm_pt_descendant(adev, &cursor))  				return -ENOENT;  			continue; -		} else if (frag >= parent_shift) { +		} else if (frag >= parent_shift && +			   cursor.level - 1 != adev->vm_manager.root_level) {  			/* If the fragment size is even larger than the parent -			 * shift we should go up one level and check it again. +			 * shift we should go up one level and check it again +			 * unless one level up is the root level.  			 */  			if (!amdgpu_vm_pt_ancestor(&cursor))  				return -ENOENT; @@ -1673,10 +1668,10 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,  		}  		/* Looks good so far, calculate parameters for the update */ -		incr = AMDGPU_GPU_PAGE_SIZE << shift; +		incr = (uint64_t)AMDGPU_GPU_PAGE_SIZE << shift;  		mask = amdgpu_vm_entries_mask(adev, cursor.level);  		pe_start = ((cursor.pfn >> shift) & mask) * 8; -		entry_end = (mask + 1) << shift; +		entry_end = (uint64_t)(mask + 1) << shift;  		entry_end += cursor.pfn & ~(entry_end - 1);  		entry_end = min(entry_end, end); @@ -1689,7 +1684,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,  					      flags | AMDGPU_PTE_FRAG(frag));  			pe_start += nptes * 8; -			dst += nptes * AMDGPU_GPU_PAGE_SIZE << shift; +			dst += (uint64_t)nptes * AMDGPU_GPU_PAGE_SIZE << shift;  			frag_start = upd_end;  			if (frag_start >= frag_end) { @@ -1701,8 +1696,17 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,  			}  		} while (frag_start < entry_end); -		if (frag >= shift) +		if (amdgpu_vm_pt_descendant(adev, &cursor)) { +			/* Mark all child entries as huge */ +			while (cursor.pfn < frag_start) { +				cursor.entry->huge = true; +				amdgpu_vm_pt_next(adev, &cursor); +			} + +		} else if (frag >= shift) { +			/* or just move on to the next on the same level. */  			amdgpu_vm_pt_next(adev, &cursor); +		}  	}  	return 0;  |