FreeBSD/sys/dev/drm2/radeon/radeon_gart.c
/**
 * radeon_vm_update_pdes - make sure that page directory is valid
 *
 * @rdev: radeon_device pointer
 * @vm: requested vm
 * @start: start of GPU address range
 * @end: end of GPU address range
 *
 * Allocates new page tables if necessary
 * and updates the page directory (cayman+).
 * Returns 0 for success, error for failure.
 *
 * Global and local mutex must be locked!
 */
make sure that page directory is valid
@rdev: radeon_device pointer
@vm: requested vm
@start: start of GPU address range
@end: end of GPU address range

Allocates new page tables if necessary
and updates the page directory (cayman+).
Returns 0 for success, error for failure.

Global and local mutex must be locked!
make sure that page directory is valid @rdev : radeon_device pointer @vm : requested vm @start : start of GPU address range @end : end of GPU address range Allocates new page tables if necessary and updates the page directory ( cayman + ) . Returns 0 for success error for failure . Global and local mutex must be locked!
static int radeon_vm_update_pdes(struct radeon_device *rdev,
				 struct radeon_vm *vm,
				 uint64_t start, uint64_t end)
{
	static const uint32_t incr = RADEON_VM_PTE_COUNT * 8;
	uint64_t last_pde = ~0, last_pt = ~0;
	unsigned count = 0;
	uint64_t pt_idx;
	int r;
	start = (start / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE;
	end = (end / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE;
	for (pt_idx = start; pt_idx <= end; ++pt_idx) {
		uint64_t pde, pt;
		if (vm->page_tables[pt_idx])
			continue;
retry:
		r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager,
				     &vm->page_tables[pt_idx],
				     RADEON_VM_PTE_COUNT * 8,
				     RADEON_GPU_PAGE_SIZE, false);
		if (r == -ENOMEM) {
			r = radeon_vm_evict(rdev, vm);
			if (r)
				return r;
			goto retry;
		} else if (r) {
			return r;
		}
		pde = vm->pd_gpu_addr + pt_idx * 8;
		pt = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]);
		if (((last_pde + 8 * count) != pde) ||
		    ((last_pt + incr * count) != pt)) {
			if (count) {
				radeon_asic_vm_set_page(rdev, last_pde,
							last_pt, count, incr,
							RADEON_VM_PAGE_VALID);
			}
			count = 1;
			last_pde = pde;
			last_pt = pt;
		} else {
			++count;
		}
	}
	if (count) {
		radeon_asic_vm_set_page(rdev, last_pde, last_pt, count,
					incr, RADEON_VM_PAGE_VALID);
	}
	return 0;
}
static int radeon_vm_update_pdes ( struct radeon_device * rdev , struct radeon_vm * vm , uint64_t start , uint64_t end ) { static const uint32_t incr = RADEON_VM_PTE_COUNT * 8 ; uint64_t last_pde = ~ 0 , last_pt = ~ 0 ; unsigned count = 0 ; uint64_t pt_idx ; int r ; start = ( start / RADEON_GPU_PAGE_SIZE ) >> RADEON_VM_BLOCK_SIZE ; end = ( end / RADEON_GPU_PAGE_SIZE ) >> RADEON_VM_BLOCK_SIZE ; for ( pt_idx = start ; pt_idx <= end ; ++ pt_idx ) { uint64_t pde , pt ; if ( vm -> page_tables [ pt_idx ] ) continue ; retry : r = radeon_sa_bo_new ( rdev , & rdev -> vm_manager . sa_manager , & vm -> page_tables [ pt_idx ] , RADEON_VM_PTE_COUNT * 8 , RADEON_GPU_PAGE_SIZE , false ) ; if ( r == - ENOMEM ) { r = radeon_vm_evict ( rdev , vm ) ; if ( r ) return r ; goto retry ; } else if ( r ) { return r ; } pde = vm -> pd_gpu_addr + pt_idx * 8 ; pt = radeon_sa_bo_gpu_addr ( vm -> page_tables [ pt_idx ] ) ; if ( ( ( last_pde + 8 * count ) != pde ) || ( ( last_pt + incr * count ) != pt ) ) { if ( count ) { radeon_asic_vm_set_page ( rdev , last_pde , last_pt , count , incr , RADEON_VM_PAGE_VALID ) ; } count = 1 ; last_pde = pde ; last_pt = pt ; } else { ++ count ; } } if ( count ) { radeon_asic_vm_set_page ( rdev , last_pde , last_pt , count , incr , RADEON_VM_PAGE_VALID ) ; } return 0 ; }
radeon_vm_update_pdes - make sure that page directory is valid
 @rdev: radeon_device pointer
 @vm: requested vm
 @start: start of GPU address range
 @end: end of GPU address range
radeon_vm_update_pdes - make sure that page directory is valid @rdev : radeon_device pointer @vm : requested vm @start : start of GPU address range @end : end of GPU address range
/* walk over the address space and update the page directory */