diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 394 |
1 files changed, 202 insertions, 192 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 3d2e00efc741..025625e7e800 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -171,7 +171,7 @@ amdgpu_ttm_job_submit(struct amdgpu_device *adev, struct amdgpu_ttm_buffer_entit { struct amdgpu_ring *ring; - ring = adev->mman.buffer_funcs_ring; + ring = to_amdgpu_ring(adev->mman.buffer_funcs_scheds[0]); amdgpu_ring_pad_ib(ring, &job->ibs[0]); WARN_ON(job->ibs[0].length_dw > num_dw); @@ -208,9 +208,10 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity, void *cpu_addr; uint64_t flags; int r; + const u64 GTT_MAX_PAGES = (AMDGPU_GTT_MAX_TRANSFER_SIZE >> PAGE_SHIFT); BUG_ON(adev->mman.buffer_funcs->copy_max_bytes < - AMDGPU_GTT_MAX_TRANSFER_SIZE * 8); + GTT_MAX_PAGES * AMDGPU_GPU_PAGES_IN_CPU_PAGE * 8); if (WARN_ON(mem->mem_type == AMDGPU_PL_PREEMPT)) return -EINVAL; @@ -230,7 +231,7 @@ static int amdgpu_ttm_map_buffer(struct amdgpu_ttm_buffer_entity *entity, offset = mm_cur->start & ~PAGE_MASK; num_pages = PFN_UP(*size + offset); - num_pages = min_t(uint32_t, num_pages, AMDGPU_GTT_MAX_TRANSFER_SIZE); + num_pages = min_t(uint32_t, num_pages, GTT_MAX_PAGES); *size = min(*size, (uint64_t)num_pages * PAGE_SIZE - offset); @@ -420,8 +421,8 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, if (old_mem->mem_type == TTM_PL_VRAM && (abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) { struct dma_fence *wipe_fence = NULL; - r = amdgpu_fill_buffer(entity, abo, 0, NULL, &wipe_fence, - AMDGPU_KERNEL_JOB_ID_MOVE_BLIT); + r = amdgpu_ttm_clear_buffer(entity, abo, NULL, &wipe_fence, + false, AMDGPU_KERNEL_JOB_ID_MOVE_BLIT); if (r) { goto error; } else if (wipe_fence) { @@ -515,6 +516,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, if (new_mem->mem_type == TTM_PL_TT || new_mem->mem_type == AMDGPU_PL_PREEMPT) { + if (old_mem && (old_mem->mem_type == TTM_PL_TT || + old_mem->mem_type == AMDGPU_PL_PREEMPT)) { + r = ttm_bo_wait_ctx(bo, ctx); + if (r) + return r; + + amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm); + } + r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, new_mem); if (r) return r; @@ -549,6 +559,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, ttm_bo_assign_mem(bo, new_mem); return 0; } + if ((old_mem->mem_type == TTM_PL_TT || + old_mem->mem_type == AMDGPU_PL_PREEMPT) && + (new_mem->mem_type == TTM_PL_TT || + new_mem->mem_type == AMDGPU_PL_PREEMPT)) { + amdgpu_bo_move_notify(bo, evict, new_mem); + ttm_resource_free(bo, &bo->resource); + ttm_bo_assign_mem(bo, new_mem); + return 0; + } if (old_mem->mem_type == AMDGPU_PL_GDS || old_mem->mem_type == AMDGPU_PL_GWS || @@ -1563,7 +1582,7 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, if (!adev->mman.sdma_access_ptr) return -EACCES; - if (!drm_dev_enter(adev_to_drm(adev), &idx)) + if (!adev->mman.buffer_funcs_enabled || !drm_dev_enter(adev_to_drm(adev), &idx)) return -ENODEV; if (write) @@ -1715,10 +1734,7 @@ static void amdgpu_ttm_init_fw_resv_region(struct amdgpu_device *adev) reserve_size = max(reserve_size, (uint32_t)280 << 20); else if (!adev->bios && amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 1, 0)) { - if (hweight32(adev->aid_mask) == 1) - reserve_size = max(reserve_size, (uint32_t)128 << 20); - else - reserve_size = max(reserve_size, (uint32_t)144 << 20); + reserve_size = max(reserve_size, (uint32_t)150 << 20); } else if (!reserve_size) reserve_size = DISCOVERY_TMR_OFFSET; @@ -2018,6 +2034,7 @@ static int amdgpu_ttm_buffer_entity_init(struct amdgpu_gtt_mgr *mgr, u32 num_gart_windows) { int i, r, num_pages; + const u64 GTT_MAX_PAGES = (AMDGPU_GTT_MAX_TRANSFER_SIZE >> PAGE_SHIFT); r = drm_sched_entity_init(&entity->base, prio, scheds, num_schedulers, NULL); if (r) @@ -2030,7 +2047,7 @@ static int amdgpu_ttm_buffer_entity_init(struct amdgpu_gtt_mgr *mgr, if (num_gart_windows == 0) return 0; - num_pages = num_gart_windows * AMDGPU_GTT_MAX_TRANSFER_SIZE; + num_pages = num_gart_windows * GTT_MAX_PAGES; r = amdgpu_gtt_mgr_alloc_entries(mgr, &entity->gart_node, num_pages, DRM_MM_INSERT_BEST); if (r) { @@ -2041,7 +2058,7 @@ static int amdgpu_ttm_buffer_entity_init(struct amdgpu_gtt_mgr *mgr, for (i = 0; i < num_gart_windows; i++) { entity->gart_window_offs[i] = amdgpu_gtt_node_to_byte_offset(&entity->gart_node) + - i * AMDGPU_GTT_MAX_TRANSFER_SIZE * PAGE_SIZE; + i * GTT_MAX_PAGES * PAGE_SIZE; } return 0; @@ -2101,20 +2118,25 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) } /* Change the size here instead of the init above so only lpfn is affected */ - amdgpu_ttm_set_buffer_funcs_status(adev, false); + amdgpu_ttm_disable_buffer_funcs(adev); #ifdef CONFIG_64BIT -#ifdef CONFIG_X86 - if (adev->gmc.xgmi.connected_to_cpu) - adev->mman.aper_base_kaddr = ioremap_cache(adev->gmc.aper_base, - adev->gmc.visible_vram_size); - - else if (adev->gmc.is_app_apu) + if (adev->gmc.xgmi.connected_to_cpu) { + void *kaddr = devm_memremap(adev->dev, adev->gmc.aper_base, + adev->gmc.visible_vram_size, + MEMREMAP_WB); + if (IS_ERR(kaddr)) + return PTR_ERR(kaddr); + adev->mman.aper_base_kaddr = (__force void __iomem *)kaddr; + } else if (adev->gmc.is_app_apu) { DRM_DEBUG_DRIVER( "No need to ioremap when real vram size is 0\n"); - else -#endif - adev->mman.aper_base_kaddr = ioremap_wc(adev->gmc.aper_base, - adev->gmc.visible_vram_size); + } else { + adev->mman.aper_base_kaddr = devm_ioremap_wc(adev->dev, + adev->gmc.aper_base, + adev->gmc.visible_vram_size); + if (!adev->mman.aper_base_kaddr) + return -ENOMEM; + } #endif amdgpu_ttm_init_vram_resv_regions(adev); @@ -2231,8 +2253,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) */ void amdgpu_ttm_fini(struct amdgpu_device *adev) { - int idx; - if (!adev->mman.initialized) return; @@ -2255,14 +2275,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW_VRAM_USAGE); amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_DRV_VRAM_USAGE); - if (drm_dev_enter(adev_to_drm(adev), &idx)) { - - if (adev->mman.aper_base_kaddr) - iounmap(adev->mman.aper_base_kaddr); - adev->mman.aper_base_kaddr = NULL; - - drm_dev_exit(idx); - } + adev->mman.aper_base_kaddr = NULL; if (!adev->gmc.is_app_apu) amdgpu_vram_mgr_fini(adev); @@ -2281,115 +2294,92 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) } /** - * amdgpu_ttm_set_buffer_funcs_status - enable/disable use of buffer functions + * amdgpu_ttm_enable_buffer_funcs - enable use of buffer functions * * @adev: amdgpu_device pointer - * @enable: true when we can use buffer functions. * - * Enable/disable use of buffer functions during suspend/resume. This should + * Enable use of buffer functions during suspend/resume. This should * only be called at bootup or when userspace isn't running. */ -void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) +void amdgpu_ttm_enable_buffer_funcs(struct amdgpu_device *adev) { struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); u32 num_clear_entities, num_move_entities; - uint64_t size; int r, i, j; if (!adev->mman.initialized || amdgpu_in_reset(adev) || - adev->mman.buffer_funcs_enabled == enable || adev->gmc.is_app_apu) + adev->mman.buffer_funcs_enabled || adev->gmc.is_app_apu) return; - if (enable) { - struct amdgpu_ring *ring; - struct drm_gpu_scheduler *sched; + if (!adev->mman.num_buffer_funcs_scheds) { + dev_warn(adev->dev, "Not enabling DMA transfers for in kernel use"); + return; + } - if (!adev->mman.buffer_funcs_ring || !adev->mman.buffer_funcs_ring->sched.ready) { - dev_warn(adev->dev, "Not enabling DMA transfers for in kernel use"); - return; - } + /* default_entity doesn't need multiple schedulers so pass only 1. */ + r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr, + &adev->mman.default_entity, + DRM_SCHED_PRIORITY_KERNEL, + adev->mman.buffer_funcs_scheds, 1, 0); + if (r < 0) { + dev_err(adev->dev, + "Failed setting up TTM entity (%d)\n", r); + return; + } - num_clear_entities = 1; - num_move_entities = 1; - ring = adev->mman.buffer_funcs_ring; - sched = &ring->sched; - r = amdgpu_ttm_buffer_entity_init(&adev->mman.gtt_mgr, - &adev->mman.default_entity, - DRM_SCHED_PRIORITY_KERNEL, - &sched, 1, 0); - if (r < 0) { - dev_err(adev->dev, - "Failed setting up TTM entity (%d)\n", r); - return; - } + num_clear_entities = MIN(adev->mman.num_buffer_funcs_scheds, TTM_NUM_MOVE_FENCES); + num_move_entities = MIN(adev->mman.num_buffer_funcs_scheds, TTM_NUM_MOVE_FENCES); - adev->mman.clear_entities = kcalloc(num_clear_entities, - sizeof(struct amdgpu_ttm_buffer_entity), - GFP_KERNEL); - atomic_set(&adev->mman.next_clear_entity, 0); - if (!adev->mman.clear_entities) - goto error_free_default_entity; + adev->mman.clear_entities = kcalloc(num_clear_entities, + sizeof(struct amdgpu_ttm_buffer_entity), + GFP_KERNEL); + atomic_set(&adev->mman.next_clear_entity, 0); + if (!adev->mman.clear_entities) + goto error_free_default_entity; - adev->mman.num_clear_entities = num_clear_entities; - - for (i = 0; i < num_clear_entities; i++) { - r = amdgpu_ttm_buffer_entity_init( - &adev->mman.gtt_mgr, &adev->mman.clear_entities[i], - DRM_SCHED_PRIORITY_NORMAL, &sched, 1, 1); - - if (r < 0) { - for (j = 0; j < i; j++) - amdgpu_ttm_buffer_entity_fini( - &adev->mman.gtt_mgr, &adev->mman.clear_entities[j]); - kfree(adev->mman.clear_entities); - adev->mman.num_clear_entities = 0; - adev->mman.clear_entities = NULL; - goto error_free_default_entity; - } + adev->mman.num_clear_entities = num_clear_entities; + + for (i = 0; i < num_clear_entities; i++) { + r = amdgpu_ttm_buffer_entity_init( + &adev->mman.gtt_mgr, + &adev->mman.clear_entities[i], + DRM_SCHED_PRIORITY_KERNEL, + adev->mman.buffer_funcs_scheds, + adev->mman.num_buffer_funcs_scheds, 1); + + if (r < 0) { + for (j = 0; j < i; j++) + amdgpu_ttm_buffer_entity_fini( + &adev->mman.gtt_mgr, &adev->mman.clear_entities[j]); + adev->mman.num_clear_entities = 0; + kfree(adev->mman.clear_entities); + goto error_free_default_entity; } + } - adev->mman.num_move_entities = num_move_entities; - atomic_set(&adev->mman.next_move_entity, 0); - for (i = 0; i < num_move_entities; i++) { - r = amdgpu_ttm_buffer_entity_init( - &adev->mman.gtt_mgr, - &adev->mman.move_entities[i], - DRM_SCHED_PRIORITY_NORMAL, &sched, 1, 2); - - if (r < 0) { - for (j = 0; j < i; j++) - amdgpu_ttm_buffer_entity_fini( - &adev->mman.gtt_mgr, &adev->mman.move_entities[j]); - adev->mman.num_move_entities = 0; - goto error_free_clear_entities; - } + adev->mman.num_move_entities = num_move_entities; + atomic_set(&adev->mman.next_move_entity, 0); + for (i = 0; i < num_move_entities; i++) { + r = amdgpu_ttm_buffer_entity_init( + &adev->mman.gtt_mgr, + &adev->mman.move_entities[i], + DRM_SCHED_PRIORITY_KERNEL, + adev->mman.buffer_funcs_scheds, + adev->mman.num_buffer_funcs_scheds, 2); + + if (r < 0) { + for (j = 0; j < i; j++) + amdgpu_ttm_buffer_entity_fini( + &adev->mman.gtt_mgr, + &adev->mman.move_entities[j]); + adev->mman.num_move_entities = 0; + goto error_free_clear_entities; } - } else { - amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, - &adev->mman.default_entity); - for (i = 0; i < adev->mman.num_clear_entities; i++) - amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, - &adev->mman.clear_entities[i]); - for (i = 0; i < adev->mman.num_move_entities; i++) - amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, - &adev->mman.move_entities[i]); - /* Drop all the old fences since re-creating the scheduler entities - * will allocate new contexts. - */ - ttm_resource_manager_cleanup(man); - kfree(adev->mman.clear_entities); - adev->mman.clear_entities = NULL; - adev->mman.num_clear_entities = 0; - adev->mman.num_move_entities = 0; } /* this just adjusts TTM size idea, which sets lpfn to the correct value */ - if (enable) - size = adev->gmc.real_vram_size; - else - size = adev->gmc.visible_vram_size; - man->size = size; - adev->mman.buffer_funcs_enabled = enable; + man->size = adev->gmc.real_vram_size; + adev->mman.buffer_funcs_enabled = true; return; @@ -2405,6 +2395,42 @@ error_free_default_entity: &adev->mman.default_entity); } +/** + * amdgpu_ttm_disable_buffer_funcs - disable use of buffer functions + * + * @adev: amdgpu_device pointer + */ +void amdgpu_ttm_disable_buffer_funcs(struct amdgpu_device *adev) +{ + struct ttm_resource_manager *man = + ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + int i; + + if (!adev->mman.buffer_funcs_enabled || amdgpu_in_reset(adev)) + return; + + amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, + &adev->mman.default_entity); + for (i = 0; i < adev->mman.num_move_entities; i++) + amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, + &adev->mman.move_entities[i]); + for (i = 0; i < adev->mman.num_clear_entities; i++) + amdgpu_ttm_buffer_entity_fini(&adev->mman.gtt_mgr, + &adev->mman.clear_entities[i]); + /* Drop all the old fences since re-creating the scheduler entities + * will allocate new contexts. + */ + ttm_resource_manager_cleanup(man); + + kfree(adev->mman.clear_entities); + adev->mman.clear_entities = NULL; + adev->mman.num_clear_entities = 0; + adev->mman.num_move_entities = 0; + + man->size = adev->gmc.visible_vram_size; + adev->mman.buffer_funcs_enabled = false; +} + static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev, struct amdgpu_ttm_buffer_entity *entity, unsigned int num_dw, @@ -2449,7 +2475,7 @@ int amdgpu_copy_buffer(struct amdgpu_device *adev, unsigned int i; int r; - ring = adev->mman.buffer_funcs_ring; + ring = to_amdgpu_ring(adev->mman.buffer_funcs_scheds[0]); if (!ring->sched.ready) { dev_err(adev->dev, @@ -2524,77 +2550,23 @@ static int amdgpu_ttm_fill_mem(struct amdgpu_device *adev, } /** - * amdgpu_ttm_clear_buffer - clear memory buffers - * @bo: amdgpu buffer object - * @resv: reservation object - * @fence: dma_fence associated with the operation + * amdgpu_ttm_clear_buffer - fill a buffer with 0 + * @entity: entity to use + * @bo: the bo to fill + * @resv: fences contained in this reservation will be used as dependencies. + * @out_fence: the fence from the last clear will be stored here. It might be + * NULL if no job was run. + * @consider_clear_status: true if region reported as cleared by amdgpu_res_cleared() + * are skipped. + * @k_job_id: trace id * - * Clear the memory buffer resource. - * - * Returns: - * 0 for success or a negative error code on failure. */ -int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, +int amdgpu_ttm_clear_buffer(struct amdgpu_ttm_buffer_entity *entity, + struct amdgpu_bo *bo, struct dma_resv *resv, - struct dma_fence **fence) -{ - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - struct amdgpu_ttm_buffer_entity *entity; - struct amdgpu_res_cursor cursor; - u64 addr; - int r = 0; - - if (!adev->mman.buffer_funcs_enabled) - return -EINVAL; - - if (!fence) - return -EINVAL; - entity = &adev->mman.clear_entities[0]; - *fence = dma_fence_get_stub(); - - amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor); - - mutex_lock(&entity->lock); - while (cursor.remaining) { - struct dma_fence *next = NULL; - u64 size; - - if (amdgpu_res_cleared(&cursor)) { - amdgpu_res_next(&cursor, cursor.size); - continue; - } - - /* Never clear more than 256MiB at once to avoid timeouts */ - size = min(cursor.size, 256ULL << 20); - - r = amdgpu_ttm_map_buffer(entity, &bo->tbo, bo->tbo.resource, &cursor, - 0, false, &size, &addr); - if (r) - goto err; - - r = amdgpu_ttm_fill_mem(adev, entity, 0, addr, size, resv, - &next, true, - AMDGPU_KERNEL_JOB_ID_TTM_CLEAR_BUFFER); - if (r) - goto err; - - dma_fence_put(*fence); - *fence = next; - - amdgpu_res_next(&cursor, size); - } -err: - mutex_unlock(&entity->lock); - - return r; -} - -int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity, - struct amdgpu_bo *bo, - uint32_t src_data, - struct dma_resv *resv, - struct dma_fence **f, - u64 k_job_id) + struct dma_fence **out_fence, + bool consider_clear_status, + u64 k_job_id) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct dma_fence *fence = NULL; @@ -2611,6 +2583,11 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity, struct dma_fence *next; uint64_t cur_size, to; + if (consider_clear_status && amdgpu_res_cleared(&dst)) { + amdgpu_res_next(&dst, dst.size); + continue; + } + /* Never fill more than 256MiB at once to avoid timeouts */ cur_size = min(dst.size, 256ULL << 20); @@ -2620,7 +2597,7 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity, goto error; r = amdgpu_ttm_fill_mem(adev, entity, - src_data, to, cur_size, resv, + 0, to, cur_size, resv, &next, true, k_job_id); if (r) goto error; @@ -2632,9 +2609,7 @@ int amdgpu_fill_buffer(struct amdgpu_ttm_buffer_entity *entity, } error: mutex_unlock(&entity->lock); - if (f) - *f = dma_fence_get(fence); - dma_fence_put(fence); + *out_fence = fence; return r; } @@ -2682,6 +2657,41 @@ int amdgpu_ttm_evict_resources(struct amdgpu_device *adev, int mem_type) return ttm_resource_manager_evict_all(&adev->mman.bdev, man); } +void amdgpu_sdma_set_buffer_funcs_scheds(struct amdgpu_device *adev, + const struct amdgpu_buffer_funcs *buffer_funcs) +{ + struct drm_gpu_scheduler *sched; + struct amdgpu_vmhub *hub; + int i, n; + + adev->mman.buffer_funcs = buffer_funcs; + + for (i = 0, n = 0; i < adev->sdma.num_instances; i++) { + if (adev->sdma.has_page_queue) + sched = &adev->sdma.instance[i].page.sched; + else + sched = &adev->sdma.instance[i].ring.sched; + + if (!sched->ready) + continue; + + adev->mman.buffer_funcs_scheds[n++] = sched; + } + + if (n == 0) { + adev->mman.num_buffer_funcs_scheds = 0; + drm_warn(&adev->ddev, "No working sdma ring available\n"); + return; + } + + /* Navi1x's workaround requires us to limit to a single SDMA sched + * for ttm. + */ + hub = &adev->vmhub[AMDGPU_GFXHUB(0)]; + adev->mman.num_buffer_funcs_scheds = hub->sdma_invalidation_workaround ? + 1 : n; +} + #if defined(CONFIG_DEBUG_FS) static int amdgpu_ttm_page_pool_show(struct seq_file *m, void *unused) |
