Am 17.05.2018 um 17:34 schrieb Alex Deucher: > On Tue, May 15, 2018 at 10:02 AM, Tom St Denis <tom.stdenis at amd.com> wrote: >> NFC just comments. >> >> (v2): Updated based on feedback from Alex Deucher. >> >> Signed-off-by: Tom St Denis <tom.stdenis at amd.com> > Reviewed-by: Alex Deucher <alexander.deucher at amd.com> Just one comment "Pin pages of memory pointed to..." better write "Grab a reference to the memory pointed to...". get_user_pages() does not pin anything! I've heard that misconception so many times now that I can't remember how often we had to explain it and we should definitely not leak it into the documentation. With that fixed the patch is Reviewed-by: Christian König <christian.koenig at amd.com>. Regards, Christian. > >> --- >> drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 347 +++++++++++++++++++++++++++++++- >> 1 file changed, 340 insertions(+), 7 deletions(-) >> >> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c >> index dfd22db13fb1..2eaaa1fb7b59 100644 >> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c >> @@ -63,16 +63,44 @@ static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev); >> /* >> * Global memory. >> */ >> + >> +/** >> + * amdgpu_ttm_mem_global_init - Initialize and acquire reference to >> + * memory object >> + * >> + * @ref: Object for initialization. >> + * >> + * This is called by drm_global_item_ref() when an object is being >> + * initialized. >> + */ >> static int amdgpu_ttm_mem_global_init(struct drm_global_reference *ref) >> { >> return ttm_mem_global_init(ref->object); >> } >> >> +/** >> + * amdgpu_ttm_mem_global_release - Drop reference to a memory object >> + * >> + * @ref: Object being removed >> + * >> + * This is called by drm_global_item_unref() when an object is being >> + * released. >> + */ >> static void amdgpu_ttm_mem_global_release(struct drm_global_reference *ref) >> { >> ttm_mem_global_release(ref->object); >> } >> >> +/** >> + * amdgpu_ttm_global_init - Initialize global TTM memory reference >> + * structures. >> + * >> + * @adev: AMDGPU device for which the global structures need to be >> + * registered. >> + * >> + * This is called as part of the AMDGPU ttm init from amdgpu_ttm_init() >> + * during bring up. >> + */ >> static int amdgpu_ttm_global_init(struct amdgpu_device *adev) >> { >> struct drm_global_reference *global_ref; >> @@ -80,7 +108,9 @@ static int amdgpu_ttm_global_init(struct amdgpu_device *adev) >> struct drm_sched_rq *rq; >> int r; >> >> + /* ensure reference is false in case init fails */ >> adev->mman.mem_global_referenced = false; >> + >> global_ref = &adev->mman.mem_global_ref; >> global_ref->global_type = DRM_GLOBAL_TTM_MEM; >> global_ref->size = sizeof(struct ttm_mem_global); >> @@ -146,6 +176,18 @@ static int amdgpu_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags) >> return 0; >> } >> >> +/** >> + * amdgpu_init_mem_type - Initialize a memory manager for a specific >> + * type of memory request. >> + * >> + * @bdev: The TTM BO device object (contains a reference to >> + * amdgpu_device) >> + * @type: The type of memory requested >> + * @man: >> + * >> + * This is called by ttm_bo_init_mm() when a buffer object is being >> + * initialized. >> + */ >> static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, >> struct ttm_mem_type_manager *man) >> { >> @@ -161,6 +203,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, >> man->default_caching = TTM_PL_FLAG_CACHED; >> break; >> case TTM_PL_TT: >> + /* GTT memory */ >> man->func = &amdgpu_gtt_mgr_func; >> man->gpu_offset = adev->gmc.gart_start; >> man->available_caching = TTM_PL_MASK_CACHING; >> @@ -193,6 +236,14 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, >> return 0; >> } >> >> +/** >> + * amdgpu_evict_flags - Compute placement flags >> + * >> + * @bo: The buffer object to evict >> + * @placement: Possible destination(s) for evicted BO >> + * >> + * Fill in placement data when ttm_bo_evict() is called >> + */ >> static void amdgpu_evict_flags(struct ttm_buffer_object *bo, >> struct ttm_placement *placement) >> { >> @@ -204,12 +255,14 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, >> .flags = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM >> }; >> >> + /* Don't handle scatter gather BOs */ >> if (bo->type == ttm_bo_type_sg) { >> placement->num_placement = 0; >> placement->num_busy_placement = 0; >> return; >> } >> >> + /* Object isn't an AMDGPU object so ignore */ >> if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) { >> placement->placement = &placements; >> placement->busy_placement = &placements; >> @@ -217,10 +270,12 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, >> placement->num_busy_placement = 1; >> return; >> } >> + >> abo = ttm_to_amdgpu_bo(bo); >> switch (bo->mem.mem_type) { >> case TTM_PL_VRAM: >> if (!adev->mman.buffer_funcs_enabled) { >> + /* Move to system memory */ >> amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU); >> } else if (adev->gmc.visible_vram_size < adev->gmc.real_vram_size && >> !(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) && >> @@ -238,6 +293,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, >> abo->placement.busy_placement = &abo->placements[1]; >> abo->placement.num_busy_placement = 1; >> } else { >> + /* Move to GTT memory */ >> amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); >> } >> break; >> @@ -248,6 +304,15 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, >> *placement = abo->placement; >> } >> >> +/** >> + * amdgpu_verify_access - Verify access for a mmap call >> + * >> + * @bo: The buffer object to map >> + * @filp: The file pointer from the process performing the mmap >> + * >> + * This is called by ttm_bo_mmap() to verify whether a process >> + * has the right to mmap a BO to their process space. >> + */ >> static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) >> { >> struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); >> @@ -265,6 +330,15 @@ static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) >> filp->private_data); >> } >> >> +/** >> + * amdgpu_move_null - Register memory for a buffer object >> + * >> + * @bo: The bo to assign the memory to >> + * @new_mem: The memory to be assigned. >> + * >> + * Assign the memory from new_mem to the memory of the buffer object >> + * bo. >> + */ >> static void amdgpu_move_null(struct ttm_buffer_object *bo, >> struct ttm_mem_reg *new_mem) >> { >> @@ -275,6 +349,10 @@ static void amdgpu_move_null(struct ttm_buffer_object *bo, >> new_mem->mm_node = NULL; >> } >> >> +/** >> + * amdgpu_mm_node_addr - Compute the GPU relative offset of a GTT >> + * buffer. >> + */ >> static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, >> struct drm_mm_node *mm_node, >> struct ttm_mem_reg *mem) >> @@ -289,9 +367,10 @@ static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, >> } >> >> /** >> - * amdgpu_find_mm_node - Helper function finds the drm_mm_node >> - * corresponding to @offset. It also modifies the offset to be >> - * within the drm_mm_node returned >> + * amdgpu_find_mm_node - Helper function finds the drm_mm_node >> + * corresponding to @offset. It also modifies >> + * the offset to be within the drm_mm_node >> + * returned >> */ >> static struct drm_mm_node *amdgpu_find_mm_node(struct ttm_mem_reg *mem, >> unsigned long *offset) >> @@ -430,7 +509,12 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, >> return r; >> } >> >> - >> +/** >> + * amdgpu_move_blit - Copy an entire buffer to another buffer >> + * >> + * This is a helper called by amdgpu_bo_move() and >> + * amdgpu_move_vram_ram() to help move buffers to and from VRAM. >> + */ >> static int amdgpu_move_blit(struct ttm_buffer_object *bo, >> bool evict, bool no_wait_gpu, >> struct ttm_mem_reg *new_mem, >> @@ -465,6 +549,11 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, >> return r; >> } >> >> +/** >> + * amdgpu_move_vram_ram - Copy VRAM buffer to RAM buffer >> + * >> + * Called by amdgpu_bo_move(). >> + */ >> static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, >> struct ttm_operation_ctx *ctx, >> struct ttm_mem_reg *new_mem) >> @@ -477,6 +566,8 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, >> int r; >> >> adev = amdgpu_ttm_adev(bo->bdev); >> + >> + /* create space/pages for new_mem in GTT space */ >> tmp_mem = *new_mem; >> tmp_mem.mm_node = NULL; >> placement.num_placement = 1; >> @@ -491,25 +582,36 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, >> return r; >> } >> >> + /* set caching flags */ >> r = ttm_tt_set_placement_caching(bo->ttm, tmp_mem.placement); >> if (unlikely(r)) { >> goto out_cleanup; >> } >> >> + /* Bind the memory to the GTT space */ >> r = ttm_tt_bind(bo->ttm, &tmp_mem, ctx); >> if (unlikely(r)) { >> goto out_cleanup; >> } >> + >> + /* blit VRAM to GTT */ >> r = amdgpu_move_blit(bo, true, ctx->no_wait_gpu, &tmp_mem, old_mem); >> if (unlikely(r)) { >> goto out_cleanup; >> } >> + >> + /* move BO (in tmp_mem) to new_mem */ >> r = ttm_bo_move_ttm(bo, ctx, new_mem); >> out_cleanup: >> ttm_bo_mem_put(bo, &tmp_mem); >> return r; >> } >> >> +/** >> + * amdgpu_move_ram_vram - Copy buffer from RAM to VRAM >> + * >> + * Called by amdgpu_bo_move(). >> + */ >> static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, >> struct ttm_operation_ctx *ctx, >> struct ttm_mem_reg *new_mem) >> @@ -522,6 +624,8 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, >> int r; >> >> adev = amdgpu_ttm_adev(bo->bdev); >> + >> + /* make space in GTT for old_mem buffer */ >> tmp_mem = *new_mem; >> tmp_mem.mm_node = NULL; >> placement.num_placement = 1; >> @@ -535,10 +639,14 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, >> if (unlikely(r)) { >> return r; >> } >> + >> + /* move/bind old memory to GTT space */ >> r = ttm_bo_move_ttm(bo, ctx, &tmp_mem); >> if (unlikely(r)) { >> goto out_cleanup; >> } >> + >> + /* copy to VRAM */ >> r = amdgpu_move_blit(bo, true, ctx->no_wait_gpu, new_mem, old_mem); >> if (unlikely(r)) { >> goto out_cleanup; >> @@ -548,6 +656,11 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, >> return r; >> } >> >> +/** >> + * amdgpu_bo_move - Move a buffer object to a new memory location >> + * >> + * Called by ttm_bo_handle_move_mem() >> + */ >> static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, >> struct ttm_operation_ctx *ctx, >> struct ttm_mem_reg *new_mem) >> @@ -613,6 +726,11 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, >> return 0; >> } >> >> +/** >> + * amdgpu_ttm_io_mem_reserve - Reserve a block of memory during a fault >> + * >> + * Called by ttm_mem_io_reserve() ultimately via ttm_bo_vm_fault() >> + */ >> static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) >> { >> struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; >> @@ -690,6 +808,14 @@ struct amdgpu_ttm_tt { >> uint32_t last_set_pages; >> }; >> >> +/** >> + * amdgpu_ttm_tt_get_user_pages - Pin pages of memory pointed to >> + * by a USERPTR pointer to memory >> + * >> + * Called by amdgpu_gem_userptr_ioctl() and amdgpu_cs_parser_bos(). >> + * This provides a wrapper around the get_user_pages() call to provide >> + * device accessible pages that back user memory. >> + */ >> int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) >> { >> struct amdgpu_ttm_tt *gtt = (void *)ttm; >> @@ -715,6 +841,7 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) >> } >> } >> >> + /* loop enough times using contiguous pages of memory */ >> do { >> unsigned num_pages = ttm->num_pages - pinned; >> uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE; >> @@ -748,6 +875,14 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) >> return r; >> } >> >> +/** >> + * amdgpu_ttm_tt_set_user_pages - Copy pages in, putting old pages >> + * as necessary. >> + * >> + * Called by amdgpu_cs_list_validate(). This creates the page list >> + * that backs user memory and will ultimately be mapped into the device >> + * address space. >> + */ >> void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages) >> { >> struct amdgpu_ttm_tt *gtt = (void *)ttm; >> @@ -762,6 +897,11 @@ void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages) >> } >> } >> >> +/** >> + * amdgpu_ttm_tt_mark_user_page - Mark pages as dirty >> + * >> + * Called while unpinning userptr pages >> + */ >> void amdgpu_ttm_tt_mark_user_pages(struct ttm_tt *ttm) >> { >> struct amdgpu_ttm_tt *gtt = (void *)ttm; >> @@ -780,7 +920,12 @@ void amdgpu_ttm_tt_mark_user_pages(struct ttm_tt *ttm) >> } >> } >> >> -/* prepare the sg table with the user pages */ >> +/** >> + * amdgpu_ttm_tt_pin_userptr - prepare the sg table with the >> + * user pages >> + * >> + * Called by amdgpu_ttm_backend_bind() >> + **/ >> static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) >> { >> struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); >> @@ -792,17 +937,20 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) >> enum dma_data_direction direction = write ? >> DMA_BIDIRECTIONAL : DMA_TO_DEVICE; >> >> + /* Allocate an SG array and squash pages into it */ >> r = sg_alloc_table_from_pages(ttm->sg, ttm->pages, ttm->num_pages, 0, >> ttm->num_pages << PAGE_SHIFT, >> GFP_KERNEL); >> if (r) >> goto release_sg; >> >> + /* Map SG to device */ >> r = -ENOMEM; >> nents = dma_map_sg(adev->dev, ttm->sg->sgl, ttm->sg->nents, direction); >> if (nents != ttm->sg->nents) >> goto release_sg; >> >> + /* convert SG to linear array of pages and dma addresses */ >> drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, >> gtt->ttm.dma_address, ttm->num_pages); >> >> @@ -813,6 +961,9 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) >> return r; >> } >> >> +/** >> + * amdgpu_ttm_tt_unpin_userptr - Unpin and unmap userptr pages >> + */ >> static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) >> { >> struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); >> @@ -826,14 +977,22 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) >> if (!ttm->sg->sgl) >> return; >> >> - /* free the sg table and pages again */ >> + /* unmap the pages mapped to the device */ >> dma_unmap_sg(adev->dev, ttm->sg->sgl, ttm->sg->nents, direction); >> >> + /* mark the pages as dirty */ >> amdgpu_ttm_tt_mark_user_pages(ttm); >> >> sg_free_table(ttm->sg); >> } >> >> + >> +/** >> + * amdgpu_ttm_backend_bind - Bind GTT memory >> + * >> + * Called by ttm_tt_bind() on behalf of ttm_bo_handle_move_mem(). >> + * This handles binding GTT memory to the device address space. >> + */ >> static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, >> struct ttm_mem_reg *bo_mem) >> { >> @@ -864,7 +1023,10 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, >> return 0; >> } >> >> + /* compute PTE flags relevant to this BO memory */ >> flags = amdgpu_ttm_tt_pte_flags(adev, ttm, bo_mem); >> + >> + /* bind pages into GART page tables */ >> gtt->offset = (u64)bo_mem->start << PAGE_SHIFT; >> r = amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages, >> ttm->pages, gtt->ttm.dma_address, flags); >> @@ -875,6 +1037,9 @@ static int amdgpu_ttm_backend_bind(struct ttm_tt *ttm, >> return r; >> } >> >> +/** >> + * amdgpu_ttm_alloc_gart - Allocate GART memory for buffer object >> + */ >> int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) >> { >> struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); >> @@ -890,6 +1055,7 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) >> amdgpu_gtt_mgr_has_gart_addr(&bo->mem)) >> return 0; >> >> + /* allocate GTT space */ >> tmp = bo->mem; >> tmp.mm_node = NULL; >> placement.num_placement = 1; >> @@ -905,7 +1071,10 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) >> if (unlikely(r)) >> return r; >> >> + /* compute PTE flags for this buffer object */ >> flags = amdgpu_ttm_tt_pte_flags(adev, bo->ttm, &tmp); >> + >> + /* Bind pages */ >> gtt->offset = (u64)tmp.start << PAGE_SHIFT; >> r = amdgpu_gart_bind(adev, gtt->offset, bo->ttm->num_pages, >> bo->ttm->pages, gtt->ttm.dma_address, flags); >> @@ -922,6 +1091,12 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) >> return 0; >> } >> >> +/** >> + * amdgpu_ttm_recover_gart - Rebind GTT pages >> + * >> + * Called by amdgpu_gtt_mgr_recover() from amdgpu_device_reset() to >> + * rebind GTT pages during a GPU reset. >> + */ >> int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo) >> { >> struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); >> @@ -941,12 +1116,19 @@ int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo) >> return r; >> } >> >> +/** >> + * amdgpu_ttm_backend_unbind - Unbind GTT mapped pages >> + * >> + * Called by ttm_tt_unbind() on behalf of ttm_bo_move_ttm() and >> + * ttm_tt_destroy(). >> + */ >> static int amdgpu_ttm_backend_unbind(struct ttm_tt *ttm) >> { >> struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); >> struct amdgpu_ttm_tt *gtt = (void *)ttm; >> int r; >> >> + /* if the pages have userptr pinning then clear that first */ >> if (gtt->userptr) >> amdgpu_ttm_tt_unpin_userptr(ttm); >> >> @@ -975,6 +1157,13 @@ static struct ttm_backend_func amdgpu_backend_func = { >> .destroy = &amdgpu_ttm_backend_destroy, >> }; >> >> +/** >> + * amdgpu_ttm_tt_create - Create a ttm_tt object for a given BO >> + * >> + * @bo: The buffer object to create a GTT ttm_tt object around >> + * >> + * Called by ttm_tt_create(). >> + */ >> static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, >> uint32_t page_flags) >> { >> @@ -988,6 +1177,8 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, >> return NULL; >> } >> gtt->ttm.ttm.func = &amdgpu_backend_func; >> + >> + /* allocate space for the uninitialized page entries */ >> if (ttm_sg_tt_init(>t->ttm, bo, page_flags)) { >> kfree(gtt); >> return NULL; >> @@ -995,6 +1186,12 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, >> return >t->ttm.ttm; >> } >> >> +/** >> + * amdgpu_ttm_tt_populate - Map GTT pages visible to the device >> + * >> + * Map the pages of a ttm_tt object to an address space visible >> + * to the underlying device. >> + */ >> static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, >> struct ttm_operation_ctx *ctx) >> { >> @@ -1002,6 +1199,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, >> struct amdgpu_ttm_tt *gtt = (void *)ttm; >> bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); >> >> + /* user pages are bound by amdgpu_ttm_tt_pin_userptr() */ >> if (gtt && gtt->userptr) { >> ttm->sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL); >> if (!ttm->sg) >> @@ -1026,9 +1224,17 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm, >> } >> #endif >> >> + /* fall back to generic helper to populate the page array >> + * and map them to the device */ >> return ttm_populate_and_map_pages(adev->dev, >t->ttm, ctx); >> } >> >> +/** >> + * amdgpu_ttm_tt_unpopulate - unmap GTT pages and unpopulate page arrays >> + * >> + * Unmaps pages of a ttm_tt object from the device address space and >> + * unpopulates the page array backing it. >> + */ >> static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) >> { >> struct amdgpu_device *adev; >> @@ -1054,9 +1260,21 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) >> } >> #endif >> >> + /* fall back to generic helper to unmap and unpopulate array */ >> ttm_unmap_and_unpopulate_pages(adev->dev, >t->ttm); >> } >> >> +/** >> + * amdgpu_ttm_tt_set_userptr - Initialize userptr GTT ttm_tt >> + * for the current task >> + * >> + * @ttm: The ttm_tt object to bind this userptr object to >> + * @addr: The address in the current tasks VM space to use >> + * @flags: Requirements of userptr object. >> + * >> + * Called by amdgpu_gem_userptr_ioctl() to bind userptr pages >> + * to current task >> + */ >> int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, >> uint32_t flags) >> { >> @@ -1076,6 +1294,9 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, >> return 0; >> } >> >> +/** >> + * amdgpu_ttm_tt_get_usermm - Return memory manager for ttm_tt object >> + */ >> struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm) >> { >> struct amdgpu_ttm_tt *gtt = (void *)ttm; >> @@ -1086,6 +1307,12 @@ struct mm_struct *amdgpu_ttm_tt_get_usermm(struct ttm_tt *ttm) >> return gtt->usermm; >> } >> >> +/** >> + * amdgpu_ttm_tt_affect_userptr - Determine if a ttm_tt object lays >> + * inside an address range for the >> + * current task. >> + * >> + */ >> bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, >> unsigned long end) >> { >> @@ -1096,10 +1323,14 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, >> if (gtt == NULL || !gtt->userptr) >> return false; >> >> + /* does the address lie within the span for the userptr memory? */ >> size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE; >> if (gtt->userptr > end || gtt->userptr + size <= start) >> return false; >> >> + /* Search the lists of tasks that hold this mapping and see >> + * if current is one of them. If it is return false. >> + */ >> spin_lock(>t->guptasklock); >> list_for_each_entry(entry, >t->guptasks, list) { >> if (entry->task == current) { >> @@ -1114,6 +1345,10 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, >> return true; >> } >> >> +/** >> + * amdgpu_ttm_tt_userptr_invalidated - Has the ttm_tt object been >> + * invalidated? >> + */ >> bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, >> int *last_invalidated) >> { >> @@ -1124,6 +1359,12 @@ bool amdgpu_ttm_tt_userptr_invalidated(struct ttm_tt *ttm, >> return prev_invalidated != *last_invalidated; >> } >> >> +/** >> + * amdgpu_ttm_tt_userptr_needs_pages - Have the pages backing this >> + * ttm_tt object been invalidated >> + * since the last time they've >> + * been set? >> + */ >> bool amdgpu_ttm_tt_userptr_needs_pages(struct ttm_tt *ttm) >> { >> struct amdgpu_ttm_tt *gtt = (void *)ttm; >> @@ -1134,6 +1375,9 @@ bool amdgpu_ttm_tt_userptr_needs_pages(struct ttm_tt *ttm) >> return atomic_read(>t->mmu_invalidations) != gtt->last_set_pages; >> } >> >> +/** >> + * amdgpu_ttm_tt_is_readonly - Is the ttm_tt object read only? >> + */ >> bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm) >> { >> struct amdgpu_ttm_tt *gtt = (void *)ttm; >> @@ -1144,6 +1388,12 @@ bool amdgpu_ttm_tt_is_readonly(struct ttm_tt *ttm) >> return !!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); >> } >> >> +/** >> + * amdgpu_ttm_tt_pte_flags - Compute PTE flags for ttm_tt object >> + * >> + * @ttm: The ttm_tt object to compute the flags for >> + * @mem: The memory registry backing this ttm_tt object >> + */ >> uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, >> struct ttm_mem_reg *mem) >> { >> @@ -1168,6 +1418,16 @@ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, >> return flags; >> } >> >> +/** >> + * amdgpu_ttm_bo_eviction_valuable - Check to see if we can evict >> + * a buffer object. >> + * >> + * Return true if eviction is sensible. Called by >> + * ttm_mem_evict_first() on behalf of ttm_bo_mem_force_space() >> + * which tries to evict buffer objects until it can find space >> + * for a new object and by ttm_bo_force_list_clean() which is >> + * used to clean out a memory space. >> + */ >> static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, >> const struct ttm_place *place) >> { >> @@ -1214,6 +1474,19 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, >> return ttm_bo_eviction_valuable(bo, place); >> } >> >> +/** >> + * amdgpu_ttm_access_memory - Read or Write memory that backs a >> + * buffer object. >> + * >> + * @bo: The buffer object to read/write >> + * @offset: Offset into buffer object >> + * @buf: Secondary buffer to write/read from >> + * @len: Length in bytes of access >> + * @write: true if writing >> + * >> + * This is used to access VRAM that backs a buffer object via MMIO >> + * access for debugging purposes. >> + */ >> static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, >> unsigned long offset, >> void *buf, int len, int write) >> @@ -1390,13 +1663,22 @@ static int amdgpu_ttm_fw_reserve_vram_init(struct amdgpu_device *adev) >> adev->fw_vram_usage.reserved_bo = NULL; >> return r; >> } >> - >> +/** >> + * amdgpu_ttm_init - Init the memory management (ttm) as well as >> + * various gtt/vram related fields. >> + * >> + * This initializes all of the memory space pools that the TTM layer >> + * will need such as the GTT space (system memory mapped to the device), >> + * VRAM (on-board memory), and on-chip memories (GDS, GWS, OA) which >> + * can be mapped per VMID. >> + */ >> int amdgpu_ttm_init(struct amdgpu_device *adev) >> { >> uint64_t gtt_size; >> int r; >> u64 vis_vram_limit; >> >> + /* initialize global references for vram/gtt */ >> r = amdgpu_ttm_global_init(adev); >> if (r) { >> return r; >> @@ -1417,6 +1699,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) >> /* We opt to avoid OOM on system pages allocations */ >> adev->mman.bdev.no_retry = true; >> >> + /* Initialize VRAM pool with all of VRAM divided into pages */ >> r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM, >> adev->gmc.real_vram_size >> PAGE_SHIFT); >> if (r) { >> @@ -1446,6 +1729,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) >> return r; >> } >> >> + /* allocate memory as required for VGA >> + * This is used for VGA emulation and pre-OS scanout buffers to >> + * avoid display artifacts while transitioning between pre-OS >> + * and driver. */ >> if (adev->gmc.stolen_size) { >> r = amdgpu_bo_create_kernel(adev, adev->gmc.stolen_size, PAGE_SIZE, >> AMDGPU_GEM_DOMAIN_VRAM, >> @@ -1457,6 +1744,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) >> DRM_INFO("amdgpu: %uM of VRAM memory ready\n", >> (unsigned) (adev->gmc.real_vram_size / (1024 * 1024))); >> >> + /* Compute GTT size, either bsaed on 3/4th the size of RAM size >> + * or whatever the user passed on module init */ >> if (amdgpu_gtt_size == -1) { >> struct sysinfo si; >> >> @@ -1467,6 +1756,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) >> } >> else >> gtt_size = (uint64_t)amdgpu_gtt_size << 20; >> + >> + /* Initialize GTT memory pool */ >> r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_TT, gtt_size >> PAGE_SHIFT); >> if (r) { >> DRM_ERROR("Failed initializing GTT heap.\n"); >> @@ -1475,6 +1766,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) >> DRM_INFO("amdgpu: %uM of GTT memory ready.\n", >> (unsigned)(gtt_size / (1024 * 1024))); >> >> + /* Initialize various on-chip memory pools */ >> adev->gds.mem.total_size = adev->gds.mem.total_size << AMDGPU_GDS_SHIFT; >> adev->gds.mem.gfx_partition_size = adev->gds.mem.gfx_partition_size << AMDGPU_GDS_SHIFT; >> adev->gds.mem.cs_partition_size = adev->gds.mem.cs_partition_size << AMDGPU_GDS_SHIFT; >> @@ -1514,6 +1806,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) >> } >> } >> >> + /* Register debugfs entries for amdgpu_ttm */ >> r = amdgpu_ttm_debugfs_init(adev); >> if (r) { >> DRM_ERROR("Failed to init debugfs\n"); >> @@ -1522,11 +1815,19 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) >> return 0; >> } >> >> +/** >> + * amdgpu_ttm_late_init - Handle any late initialization for >> + * amdgpu_ttm >> + */ >> void amdgpu_ttm_late_init(struct amdgpu_device *adev) >> { >> + /* return the VGA stolen memory (if any) back to VRAM */ >> amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, NULL); >> } >> >> +/** >> + * amdgpu_ttm_fini - De-initialize the TTM memory pools >> + */ >> void amdgpu_ttm_fini(struct amdgpu_device *adev) >> { >> if (!adev->mman.initialized) >> @@ -1854,6 +2155,11 @@ static const struct drm_info_list amdgpu_ttm_debugfs_list[] = { >> #endif >> }; >> >> +/** >> + * amdgpu_ttm_vram_read - Linear read access to VRAM >> + * >> + * Accesses VRAM via MMIO for debugging purposes. >> + */ >> static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf, >> size_t size, loff_t *pos) >> { >> @@ -1893,6 +2199,11 @@ static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf, >> return result; >> } >> >> +/** >> + * amdgpu_ttm_vram_write - Linear write access to VRAM >> + * >> + * Accesses VRAM via MMIO for debugging purposes. >> + */ >> static ssize_t amdgpu_ttm_vram_write(struct file *f, const char __user *buf, >> size_t size, loff_t *pos) >> { >> @@ -1941,6 +2252,9 @@ static const struct file_operations amdgpu_ttm_vram_fops = { >> >> #ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS >> >> +/** >> + * amdgpu_ttm_gtt_read - Linear read access to GTT memory >> + */ >> static ssize_t amdgpu_ttm_gtt_read(struct file *f, char __user *buf, >> size_t size, loff_t *pos) >> { >> @@ -1988,6 +2302,13 @@ static const struct file_operations amdgpu_ttm_gtt_fops = { >> >> #endif >> >> +/** >> + * amdgpu_iomem_read - Virtual read access to GPU mapped memory >> + * >> + * This function is used to read memory that has been mapped to the >> + * GPU and the known addresses are not physical addresses but instead >> + * bus addresses (e.g., what you'd put in an IB or ring buffer). >> + */ >> static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, >> size_t size, loff_t *pos) >> { >> @@ -1996,6 +2317,7 @@ static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, >> ssize_t result = 0; >> int r; >> >> + /* retrieve the IOMMU domain if any for this device */ >> dom = iommu_get_domain_for_dev(adev->dev); >> >> while (size) { >> @@ -2008,6 +2330,10 @@ static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, >> >> bytes = bytes < size ? bytes : size; >> >> + /* Translate the bus address to a physical address. If >> + * the domain is NULL it means there is no IOMMU active >> + * and the address translation is the identity >> + */ >> addr = dom ? iommu_iova_to_phys(dom, addr) : addr; >> >> pfn = addr >> PAGE_SHIFT; >> @@ -2032,6 +2358,13 @@ static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf, >> return result; >> } >> >> +/** >> + * amdgpu_iomem_write - Virtual write access to GPU mapped memory >> + * >> + * This function is used to write memory that has been mapped to the >> + * GPU and the known addresses are not physical addresses but instead >> + * bus addresses (e.g., what you'd put in an IB or ring buffer). >> + */ >> static ssize_t amdgpu_iomem_write(struct file *f, const char __user *buf, >> size_t size, loff_t *pos) >> { >> -- >> 2.14.3 >> >> _______________________________________________ >> amd-gfx mailing list >> amd-gfx at lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/amd-gfx > _______________________________________________ > amd-gfx mailing list > amd-gfx at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx