From 03f48dd5d2085b978353a804635b6d34e77a5635 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 15 Aug 2016 17:00:22 +0200 Subject: drm/amdgpu: add AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS flag v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a flag noting that a BO must be created using linear VRAM and set this flag on all in kernel users where appropriate. Hopefully I haven't missed anything. v2: add it in a few more places, fix CPU mapping. v3: rename to VRAM_CONTIGUOUS, fix typo in CS code. Signed-off-by: Christian König Reviewed-by: Edward O'Callaghan Tested-by: Mike Lothian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index dcaf691f56b5..a06cf9988912 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1119,7 +1119,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) r = amdgpu_bo_create(adev, 256 * 1024, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, - AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, &adev->stollen_vga_memory); if (r) { return r; -- cgit v1.2.3 From 8892f153c83e521aff2ee7ac620856e2983cd7a0 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 17 Aug 2016 10:46:52 +0200 Subject: drm/amdgpu: enable amdgpu_move_blit to handle multiple MM nodes v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to move scattered buffers around. v2: fix a couple of typos, handle scattered to scattered moves as well. Signed-off-by: Christian König Reviewed-by: Edward O'Callaghan Tested-by: Mike Lothian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 118 +++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index a06cf9988912..1427c40c70bb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -260,64 +260,116 @@ static void amdgpu_move_null(struct ttm_buffer_object *bo, new_mem->mm_node = NULL; } -static int amdgpu_move_blit(struct ttm_buffer_object *bo, - bool evict, bool no_wait_gpu, - struct ttm_mem_reg *new_mem, - struct ttm_mem_reg *old_mem) +static int amdgpu_mm_node_addr(struct ttm_buffer_object *bo, + struct drm_mm_node *mm_node, + struct ttm_mem_reg *mem, + uint64_t *addr) { - struct amdgpu_device *adev; - struct amdgpu_ring *ring; - uint64_t old_start, new_start; - struct fence *fence; int r; - adev = amdgpu_get_adev(bo->bdev); - ring = adev->mman.buffer_funcs_ring; - - switch (old_mem->mem_type) { + switch (mem->mem_type) { case TTM_PL_TT: - r = amdgpu_ttm_bind(bo, old_mem); + r = amdgpu_ttm_bind(bo, mem); if (r) return r; case TTM_PL_VRAM: - old_start = (u64)old_mem->start << PAGE_SHIFT; - old_start += bo->bdev->man[old_mem->mem_type].gpu_offset; + *addr = mm_node->start << PAGE_SHIFT; + *addr += bo->bdev->man[mem->mem_type].gpu_offset; break; default: - DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); + DRM_ERROR("Unknown placement %d\n", mem->mem_type); return -EINVAL; } - switch (new_mem->mem_type) { - case TTM_PL_TT: - r = amdgpu_ttm_bind(bo, new_mem); - if (r) - return r; - case TTM_PL_VRAM: - new_start = (u64)new_mem->start << PAGE_SHIFT; - new_start += bo->bdev->man[new_mem->mem_type].gpu_offset; - break; - default: - DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); - return -EINVAL; - } + return 0; +} + +static int amdgpu_move_blit(struct ttm_buffer_object *bo, + bool evict, bool no_wait_gpu, + struct ttm_mem_reg *new_mem, + struct ttm_mem_reg *old_mem) +{ + struct amdgpu_device *adev = amdgpu_get_adev(bo->bdev); + struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; + + struct drm_mm_node *old_mm, *new_mm; + uint64_t old_start, old_size, new_start, new_size; + unsigned long num_pages; + struct fence *fence = NULL; + int r; + + BUILD_BUG_ON((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) != 0); + if (!ring->ready) { DRM_ERROR("Trying to move memory with ring turned off.\n"); return -EINVAL; } - BUILD_BUG_ON((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) != 0); + old_mm = old_mem->mm_node; + r = amdgpu_mm_node_addr(bo, old_mm, old_mem, &old_start); + if (r) + return r; + old_size = old_mm->size; + - r = amdgpu_copy_buffer(ring, old_start, new_start, - new_mem->num_pages * PAGE_SIZE, /* bytes */ - bo->resv, &fence, false); + new_mm = new_mem->mm_node; + r = amdgpu_mm_node_addr(bo, new_mm, new_mem, &new_start); if (r) return r; + new_size = new_mm->size; + + num_pages = new_mem->num_pages; + while (num_pages) { + unsigned long cur_pages = min(old_size, new_size); + struct fence *next; + + r = amdgpu_copy_buffer(ring, old_start, new_start, + cur_pages * PAGE_SIZE, + bo->resv, &next, false); + if (r) + goto error; + + fence_put(fence); + fence = next; + + num_pages -= cur_pages; + if (!num_pages) + break; + + old_size -= cur_pages; + if (!old_size) { + r = amdgpu_mm_node_addr(bo, ++old_mm, old_mem, + &old_start); + if (r) + goto error; + old_size = old_mm->size; + } else { + old_start += cur_pages * PAGE_SIZE; + } + + new_size -= cur_pages; + if (!new_size) { + r = amdgpu_mm_node_addr(bo, ++new_mm, new_mem, + &new_start); + if (r) + goto error; + + new_size = new_mm->size; + } else { + new_start += cur_pages * PAGE_SIZE; + } + } r = ttm_bo_pipeline_move(bo, fence, evict, new_mem); fence_put(fence); return r; + +error: + if (fence) + fence_wait(fence, false); + fence_put(fence); + return r; } static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, -- cgit v1.2.3 From 6a7f76e70fac0b1d41e7c5e193c33b1ee7e902c6 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 24 Aug 2016 15:51:49 +0200 Subject: drm/amdgpu: add VRAM manager v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split VRAM allocations into 4MB blocks. v2: fix typo in comment, some suggested cleanups v3: document how to disable the feature, fix rebase issue Signed-off-by: Christian König Reviewed-by: Edward O'Callaghan Tested-by: Mike Lothian Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 222 +++++++++++++++++++++++++++ 7 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 248a05d02917..41bd2bf28f4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -24,7 +24,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ atombios_encoders.o amdgpu_sa.o atombios_i2c.o \ amdgpu_prime.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ - amdgpu_gtt_mgr.o + amdgpu_gtt_mgr.o amdgpu_vram_mgr.o # add asic specific block amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 039b57e4644c..1296f5967bd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -97,6 +97,7 @@ extern char *amdgpu_disable_cu; extern int amdgpu_sclk_deep_sleep_en; extern char *amdgpu_virtual_display; extern unsigned amdgpu_pp_feature_mask; +extern int amdgpu_vram_page_split; #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 #define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 246bbd1ab5ec..9df66d1e843d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1052,6 +1052,13 @@ static void amdgpu_check_arguments(struct amdgpu_device *adev) amdgpu_vm_block_size); amdgpu_vm_block_size = 9; } + + if ((amdgpu_vram_page_split != -1 && amdgpu_vram_page_split < 16) || + !amdgpu_check_pot_argument(amdgpu_vram_page_split)) { + dev_warn(adev->dev, "invalid VRAM page split (%d)\n", + amdgpu_vram_page_split); + amdgpu_vram_page_split = 1024; + } } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 2201f05ecc94..528d6531dd49 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -85,6 +85,7 @@ int amdgpu_vm_size = 64; int amdgpu_vm_block_size = -1; int amdgpu_vm_fault_stop = 0; int amdgpu_vm_debug = 0; +int amdgpu_vram_page_split = 1024; int amdgpu_exp_hw_support = 0; int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; @@ -165,6 +166,9 @@ module_param_named(vm_fault_stop, amdgpu_vm_fault_stop, int, 0444); MODULE_PARM_DESC(vm_debug, "Debug VM handling (0 = disabled (default), 1 = enabled)"); module_param_named(vm_debug, amdgpu_vm_debug, int, 0644); +MODULE_PARM_DESC(vram_page_split, "Number of pages after we split VRAM allocations (default 1024, -1 = disable)"); +module_param_named(vram_page_split, amdgpu_vram_page_split, int, 0444); + MODULE_PARM_DESC(exp_hw_support, "experimental hw support (1 = enable, 0 = disable (default))"); module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1427c40c70bb..f757f68418b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -168,7 +168,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, break; case TTM_PL_VRAM: /* "On-card" video ram */ - man->func = &ttm_bo_manager_func; + man->func = &amdgpu_vram_mgr_func; man->gpu_offset = adev->mc.vram_start; man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 9812c805326c..d1c00c04782f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -66,6 +66,7 @@ struct amdgpu_mman { }; extern const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func; +extern const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func; int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, struct ttm_buffer_object *tbo, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c new file mode 100644 index 000000000000..180eed7c8bca --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -0,0 +1,222 @@ +/* + * Copyright 2016 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Christian König + */ + +#include +#include "amdgpu.h" + +struct amdgpu_vram_mgr { + struct drm_mm mm; + spinlock_t lock; +}; + +/** + * amdgpu_vram_mgr_init - init VRAM manager and DRM MM + * + * @man: TTM memory type manager + * @p_size: maximum size of VRAM + * + * Allocate and initialize the VRAM manager. + */ +static int amdgpu_vram_mgr_init(struct ttm_mem_type_manager *man, + unsigned long p_size) +{ + struct amdgpu_vram_mgr *mgr; + + mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); + if (!mgr) + return -ENOMEM; + + drm_mm_init(&mgr->mm, 0, p_size); + spin_lock_init(&mgr->lock); + man->priv = mgr; + return 0; +} + +/** + * amdgpu_vram_mgr_fini - free and destroy VRAM manager + * + * @man: TTM memory type manager + * + * Destroy and free the VRAM manager, returns -EBUSY if ranges are still + * allocated inside it. + */ +static int amdgpu_vram_mgr_fini(struct ttm_mem_type_manager *man) +{ + struct amdgpu_vram_mgr *mgr = man->priv; + + spin_lock(&mgr->lock); + if (!drm_mm_clean(&mgr->mm)) { + spin_unlock(&mgr->lock); + return -EBUSY; + } + + drm_mm_takedown(&mgr->mm); + spin_unlock(&mgr->lock); + kfree(mgr); + man->priv = NULL; + return 0; +} + +/** + * amdgpu_vram_mgr_new - allocate new ranges + * + * @man: TTM memory type manager + * @tbo: TTM BO we need this range for + * @place: placement flags and restrictions + * @mem: the resulting mem object + * + * Allocate VRAM for the given BO. + */ +static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, + struct ttm_buffer_object *tbo, + const struct ttm_place *place, + struct ttm_mem_reg *mem) +{ + struct amdgpu_bo *bo = container_of(tbo, struct amdgpu_bo, tbo); + struct amdgpu_vram_mgr *mgr = man->priv; + struct drm_mm *mm = &mgr->mm; + struct drm_mm_node *nodes; + enum drm_mm_search_flags sflags = DRM_MM_SEARCH_DEFAULT; + enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT; + unsigned long lpfn, num_nodes, pages_per_node, pages_left; + unsigned i; + int r; + + lpfn = place->lpfn; + if (!lpfn) + lpfn = man->size; + + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS || + amdgpu_vram_page_split == -1) { + pages_per_node = ~0ul; + num_nodes = 1; + } else { + pages_per_node = max((uint32_t)amdgpu_vram_page_split, + mem->page_alignment); + num_nodes = DIV_ROUND_UP(mem->num_pages, pages_per_node); + } + + nodes = kcalloc(num_nodes, sizeof(*nodes), GFP_KERNEL); + if (!nodes) + return -ENOMEM; + + if (place->flags & TTM_PL_FLAG_TOPDOWN) { + sflags = DRM_MM_SEARCH_BELOW; + aflags = DRM_MM_CREATE_TOP; + } + + pages_left = mem->num_pages; + + spin_lock(&mgr->lock); + for (i = 0; i < num_nodes; ++i) { + unsigned long pages = min(pages_left, pages_per_node); + uint32_t alignment = mem->page_alignment; + + if (pages == pages_per_node) + alignment = pages_per_node; + else + sflags |= DRM_MM_SEARCH_BEST; + + r = drm_mm_insert_node_in_range_generic(mm, &nodes[i], pages, + alignment, 0, + place->fpfn, lpfn, + sflags, aflags); + if (unlikely(r)) + goto error; + + pages_left -= pages; + } + spin_unlock(&mgr->lock); + + mem->start = num_nodes == 1 ? nodes[0].start : AMDGPU_BO_INVALID_OFFSET; + mem->mm_node = nodes; + + return 0; + +error: + while (i--) + drm_mm_remove_node(&nodes[i]); + spin_unlock(&mgr->lock); + + kfree(nodes); + return r == -ENOSPC ? 0 : r; +} + +/** + * amdgpu_vram_mgr_del - free ranges + * + * @man: TTM memory type manager + * @tbo: TTM BO we need this range for + * @place: placement flags and restrictions + * @mem: TTM memory object + * + * Free the allocated VRAM again. + */ +static void amdgpu_vram_mgr_del(struct ttm_mem_type_manager *man, + struct ttm_mem_reg *mem) +{ + struct amdgpu_vram_mgr *mgr = man->priv; + struct drm_mm_node *nodes = mem->mm_node; + unsigned pages = mem->num_pages; + + if (!mem->mm_node) + return; + + spin_lock(&mgr->lock); + while (pages) { + pages -= nodes->size; + drm_mm_remove_node(nodes); + ++nodes; + } + spin_unlock(&mgr->lock); + + kfree(mem->mm_node); + mem->mm_node = NULL; +} + +/** + * amdgpu_vram_mgr_debug - dump VRAM table + * + * @man: TTM memory type manager + * @prefix: text prefix + * + * Dump the table content using printk. + */ +static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man, + const char *prefix) +{ + struct amdgpu_vram_mgr *mgr = man->priv; + + spin_lock(&mgr->lock); + drm_mm_debug_table(&mgr->mm, prefix); + spin_unlock(&mgr->lock); +} + +const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = { + amdgpu_vram_mgr_init, + amdgpu_vram_mgr_fini, + amdgpu_vram_mgr_new, + amdgpu_vram_mgr_del, + amdgpu_vram_mgr_debug +}; -- cgit v1.2.3 From a7d64de659946e852cd8f2a9691a21ddbb4ebc86 Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 15 Sep 2016 14:58:48 +0200 Subject: drm/amdgpu: remove adev pointer from struct amdgpu_bo v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's completely pointless to have two pointers to the device in the same structure. v2: rename function to amdgpu_ttm_adev, fix typos Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 10 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 7 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c | 4 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 50 ++++++++++++++++-------------- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 43 ++++++++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- 9 files changed, 65 insertions(+), 62 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 4e51009283a4..1c874fd525a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -465,7 +465,6 @@ struct amdgpu_bo { */ struct list_head va; /* Constant after initialization */ - struct amdgpu_device *adev; struct drm_gem_object gem_base; struct amdgpu_bo *parent; struct amdgpu_bo *shadow; @@ -2127,6 +2126,11 @@ struct amdgpu_device { }; +static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) +{ + return container_of(bdev, struct amdgpu_device, mman.bdev); +} + bool amdgpu_device_is_px(struct drm_device *dev); int amdgpu_device_init(struct amdgpu_device *adev, struct drm_device *ddev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 187c3662b72c..504ae09d3991 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -355,6 +355,7 @@ static void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, struct amdgpu_bo *bo) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); u64 initial_bytes_moved; uint32_t domain; int r; @@ -372,9 +373,9 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, retry: amdgpu_ttm_placement_from_domain(bo, domain); - initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved); + initial_bytes_moved = atomic64_read(&adev->num_bytes_moved); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); - p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) - + p->bytes_moved += atomic64_read(&adev->num_bytes_moved) - initial_bytes_moved; if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) { @@ -400,6 +401,7 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, struct amdgpu_bo_list_entry *candidate = p->evictable; struct amdgpu_bo *bo = candidate->robj; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); u64 initial_bytes_moved; uint32_t other; @@ -420,9 +422,9 @@ static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p, /* Good we can try to move this BO somewhere else */ amdgpu_ttm_placement_from_domain(bo, other); - initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved); + initial_bytes_moved = atomic64_read(&adev->num_bytes_moved); r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false); - p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) - + p->bytes_moved += atomic64_read(&adev->num_bytes_moved) - initial_bytes_moved; if (unlikely(r)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 3ad0bf6ce3e4..d4fce326502b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -116,10 +116,11 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev) * Call from drm_gem_handle_create which appear in both new and open ioctl * case. */ -int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv) +int amdgpu_gem_object_open(struct drm_gem_object *obj, + struct drm_file *file_priv) { struct amdgpu_bo *abo = gem_to_amdgpu_bo(obj); - struct amdgpu_device *adev = abo->adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); struct amdgpu_fpriv *fpriv = file_priv->driver_priv; struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_va *bo_va; @@ -142,7 +143,7 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, struct drm_file *file_priv) { struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); - struct amdgpu_device *adev = bo->adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct amdgpu_fpriv *fpriv = file_priv->driver_priv; struct amdgpu_vm *vm = &fpriv->vm; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c index 32fa7b7913f7..7ea3cacf9f9f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c @@ -285,7 +285,7 @@ free_rmn: int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr) { unsigned long end = addr + amdgpu_bo_size(bo) - 1; - struct amdgpu_device *adev = bo->adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct amdgpu_mn *rmn; struct amdgpu_mn_node *node = NULL; struct list_head bos; @@ -340,7 +340,7 @@ int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr) */ void amdgpu_mn_unregister(struct amdgpu_bo *bo) { - struct amdgpu_device *adev = bo->adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct amdgpu_mn *rmn; struct list_head *head; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index c6754e71e1f5..6efa8d73b394 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -88,18 +88,19 @@ static void amdgpu_update_memory_usage(struct amdgpu_device *adev, static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo) { + struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); struct amdgpu_bo *bo; bo = container_of(tbo, struct amdgpu_bo, tbo); - amdgpu_update_memory_usage(bo->adev, &bo->tbo.mem, NULL); + amdgpu_update_memory_usage(adev, &bo->tbo.mem, NULL); drm_gem_object_release(&bo->gem_base); amdgpu_bo_unref(&bo->parent); if (!list_empty(&bo->shadow_list)) { - mutex_lock(&bo->adev->shadow_list_lock); + mutex_lock(&adev->shadow_list_lock); list_del_init(&bo->shadow_list); - mutex_unlock(&bo->adev->shadow_list_lock); + mutex_unlock(&adev->shadow_list_lock); } kfree(bo->metadata); kfree(bo); @@ -210,8 +211,10 @@ static void amdgpu_ttm_placement_init(struct amdgpu_device *adev, void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain) { - amdgpu_ttm_placement_init(abo->adev, &abo->placement, - abo->placements, domain, abo->flags); + struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); + + amdgpu_ttm_placement_init(adev, &abo->placement, abo->placements, + domain, abo->flags); } static void amdgpu_fill_placement_to_bo(struct amdgpu_bo *bo, @@ -357,7 +360,6 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, kfree(bo); return r; } - bo->adev = adev; INIT_LIST_HEAD(&bo->shadow_list); INIT_LIST_HEAD(&bo->va); bo->prefered_domains = domain & (AMDGPU_GEM_DOMAIN_VRAM | @@ -622,6 +624,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 min_offset, u64 max_offset, u64 *gpu_addr) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); int r, i; unsigned fpfn, lpfn; @@ -657,12 +660,12 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, if ((bo->placements[i].flags & TTM_PL_FLAG_VRAM) && !(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) && (!max_offset || max_offset > - bo->adev->mc.visible_vram_size)) { + adev->mc.visible_vram_size)) { if (WARN_ON_ONCE(min_offset > - bo->adev->mc.visible_vram_size)) + adev->mc.visible_vram_size)) return -EINVAL; fpfn = min_offset >> PAGE_SHIFT; - lpfn = bo->adev->mc.visible_vram_size >> PAGE_SHIFT; + lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT; } else { fpfn = min_offset >> PAGE_SHIFT; lpfn = max_offset >> PAGE_SHIFT; @@ -677,12 +680,12 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); if (unlikely(r)) { - dev_err(bo->adev->dev, "%p pin failed\n", bo); + dev_err(adev->dev, "%p pin failed\n", bo); goto error; } r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem); if (unlikely(r)) { - dev_err(bo->adev->dev, "%p bind failed\n", bo); + dev_err(adev->dev, "%p bind failed\n", bo); goto error; } @@ -690,11 +693,11 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, if (gpu_addr != NULL) *gpu_addr = amdgpu_bo_gpu_offset(bo); if (domain == AMDGPU_GEM_DOMAIN_VRAM) { - bo->adev->vram_pin_size += amdgpu_bo_size(bo); + adev->vram_pin_size += amdgpu_bo_size(bo); if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) - bo->adev->invisible_pin_size += amdgpu_bo_size(bo); + adev->invisible_pin_size += amdgpu_bo_size(bo); } else if (domain == AMDGPU_GEM_DOMAIN_GTT) { - bo->adev->gart_pin_size += amdgpu_bo_size(bo); + adev->gart_pin_size += amdgpu_bo_size(bo); } error: @@ -708,10 +711,11 @@ int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain, u64 *gpu_addr) int amdgpu_bo_unpin(struct amdgpu_bo *bo) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); int r, i; if (!bo->pin_count) { - dev_warn(bo->adev->dev, "%p unpin not necessary\n", bo); + dev_warn(adev->dev, "%p unpin not necessary\n", bo); return 0; } bo->pin_count--; @@ -723,16 +727,16 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo) } r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); if (unlikely(r)) { - dev_err(bo->adev->dev, "%p validate failed for unpin\n", bo); + dev_err(adev->dev, "%p validate failed for unpin\n", bo); goto error; } if (bo->tbo.mem.mem_type == TTM_PL_VRAM) { - bo->adev->vram_pin_size -= amdgpu_bo_size(bo); + adev->vram_pin_size -= amdgpu_bo_size(bo); if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) - bo->adev->invisible_pin_size -= amdgpu_bo_size(bo); + adev->invisible_pin_size -= amdgpu_bo_size(bo); } else if (bo->tbo.mem.mem_type == TTM_PL_TT) { - bo->adev->gart_pin_size -= amdgpu_bo_size(bo); + adev->gart_pin_size -= amdgpu_bo_size(bo); } error: @@ -857,6 +861,7 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer, void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; struct ttm_mem_reg *old_mem = &bo->mem; @@ -864,21 +869,21 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, return; abo = container_of(bo, struct amdgpu_bo, tbo); - amdgpu_vm_bo_invalidate(abo->adev, abo); + amdgpu_vm_bo_invalidate(adev, abo); /* update statistics */ if (!new_mem) return; /* move_notify is called before move happens */ - amdgpu_update_memory_usage(abo->adev, &bo->mem, new_mem); + amdgpu_update_memory_usage(adev, &bo->mem, new_mem); trace_amdgpu_ttm_bo_move(abo, new_mem->mem_type, old_mem->mem_type); } int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) { - struct amdgpu_device *adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; unsigned long offset, size, lpfn; int i, r; @@ -887,7 +892,6 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) return 0; abo = container_of(bo, struct amdgpu_bo, tbo); - adev = abo->adev; if (bo->mem.mem_type != TTM_PL_VRAM) return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 8255034d73eb..d3baf834ac24 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -71,12 +71,13 @@ static inline unsigned amdgpu_mem_type_to_domain(u32 mem_type) */ static inline int amdgpu_bo_reserve(struct amdgpu_bo *bo, bool no_intr) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); int r; r = ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL); if (unlikely(r != 0)) { if (r != -ERESTARTSYS) - dev_err(bo->adev->dev, "%p reserve failed\n", bo); + dev_err(adev->dev, "%p reserve failed\n", bo); return r; } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index f757f68418b7..414fa8fa8488 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -51,16 +51,6 @@ static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev); static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev); -static struct amdgpu_device *amdgpu_get_adev(struct ttm_bo_device *bdev) -{ - struct amdgpu_mman *mman; - struct amdgpu_device *adev; - - mman = container_of(bdev, struct amdgpu_mman, bdev); - adev = container_of(mman, struct amdgpu_device, mman); - return adev; -} - /* * Global memory. @@ -150,7 +140,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, { struct amdgpu_device *adev; - adev = amdgpu_get_adev(bdev); + adev = amdgpu_ttm_adev(bdev); switch (type) { case TTM_PL_SYSTEM: @@ -195,6 +185,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, static void amdgpu_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *placement) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_bo *abo; static struct ttm_place placements = { .fpfn = 0, @@ -213,7 +204,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, abo = container_of(bo, struct amdgpu_bo, tbo); switch (bo->mem.mem_type) { case TTM_PL_VRAM: - if (abo->adev->mman.buffer_funcs_ring->ready == false) { + if (adev->mman.buffer_funcs_ring->ready == false) { amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU); } else { amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); @@ -229,7 +220,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, * allocating address space for the BO. */ abo->placements[i].lpfn = - abo->adev->mc.gtt_size >> PAGE_SHIFT; + adev->mc.gtt_size >> PAGE_SHIFT; } } break; @@ -290,7 +281,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, struct ttm_mem_reg *old_mem) { - struct amdgpu_device *adev = amdgpu_get_adev(bo->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; struct drm_mm_node *old_mm, *new_mm; @@ -384,7 +375,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, struct ttm_placement placement; int r; - adev = amdgpu_get_adev(bo->bdev); + adev = amdgpu_ttm_adev(bo->bdev); tmp_mem = *new_mem; tmp_mem.mm_node = NULL; placement.num_placement = 1; @@ -431,7 +422,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, struct ttm_place placements; int r; - adev = amdgpu_get_adev(bo->bdev); + adev = amdgpu_ttm_adev(bo->bdev); tmp_mem = *new_mem; tmp_mem.mm_node = NULL; placement.num_placement = 1; @@ -474,7 +465,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, if (WARN_ON_ONCE(abo->pin_count > 0)) return -EINVAL; - adev = amdgpu_get_adev(bo->bdev); + adev = amdgpu_ttm_adev(bo->bdev); /* remember the eviction */ if (evict) @@ -527,7 +518,7 @@ memcpy: 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]; - struct amdgpu_device *adev = amdgpu_get_adev(bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); mem->bus.addr = NULL; mem->bus.offset = 0; @@ -659,7 +650,7 @@ release_pages: /* prepare the sg table with the user pages */ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) { - struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; unsigned nents; int r; @@ -691,7 +682,7 @@ release_sg: static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm) { - struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; struct sg_page_iter sg_iter; @@ -851,7 +842,7 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_bo_device *bdev, struct amdgpu_device *adev; struct amdgpu_ttm_tt *gtt; - adev = amdgpu_get_adev(bdev); + adev = amdgpu_ttm_adev(bdev); gtt = kzalloc(sizeof(struct amdgpu_ttm_tt), GFP_KERNEL); if (gtt == NULL) { @@ -895,7 +886,7 @@ static int amdgpu_ttm_tt_populate(struct ttm_tt *ttm) return 0; } - adev = amdgpu_get_adev(ttm->bdev); + adev = amdgpu_ttm_adev(ttm->bdev); #ifdef CONFIG_SWIOTLB if (swiotlb_nr_tbl()) { @@ -941,7 +932,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_tt *ttm) if (slave) return; - adev = amdgpu_get_adev(ttm->bdev); + adev = amdgpu_ttm_adev(ttm->bdev); #ifdef CONFIG_SWIOTLB if (swiotlb_nr_tbl()) { @@ -1064,7 +1055,7 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, static void amdgpu_ttm_lru_removal(struct ttm_buffer_object *tbo) { - struct amdgpu_device *adev = amdgpu_get_adev(tbo->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); unsigned i, j; for (i = 0; i < AMDGPU_TTM_LRU_SIZE; ++i) { @@ -1081,7 +1072,7 @@ static void amdgpu_ttm_lru_removal(struct ttm_buffer_object *tbo) static struct amdgpu_mman_lru *amdgpu_ttm_lru(struct ttm_buffer_object *tbo) { - struct amdgpu_device *adev = amdgpu_get_adev(tbo->bdev); + struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); unsigned log2_size = min(ilog2(tbo->num_pages), AMDGPU_TTM_LRU_SIZE - 1); @@ -1370,7 +1361,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct reservation_object *resv, struct fence **fence) { - struct amdgpu_device *adev = bo->adev; + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct amdgpu_job *job; struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index 4cf3ca755810..d67eadaa91a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -931,7 +931,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, if (r) return r; - if (!bo->adev->uvd.address_64_bit) { + if (!ring->adev->uvd.address_64_bit) { amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM); amdgpu_uvd_force_into_uvd_segment(bo); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 840ac52f45b6..f4b78b66444d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1195,7 +1195,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, flags = amdgpu_ttm_tt_pte_flags(adev, bo_va->bo->tbo.ttm, mem); gtt_flags = (amdgpu_ttm_is_bound(bo_va->bo->tbo.ttm) && - adev == bo_va->bo->adev) ? flags : 0; + adev == amdgpu_ttm_adev(bo_va->bo->tbo.bdev)) ? flags : 0; spin_lock(&vm->status_lock); if (!list_empty(&bo_va->vm_status)) -- cgit v1.2.3 From a2ab19fed9d1dc5a7a2ced44f4b289885c522a8f Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 30 Aug 2016 17:26:04 +0200 Subject: drm/ttm: make eviction decision a driver callback v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way the driver can decide if it is valuable to evict a BO or not. The current implementation is added as default to all existing drivers. v2: fix some typos found during internal testing Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 1 + drivers/gpu/drm/ast/ast_ttm.c | 1 + drivers/gpu/drm/bochs/bochs_mm.c | 1 + drivers/gpu/drm/cirrus/cirrus_ttm.c | 1 + drivers/gpu/drm/mgag200/mgag200_ttm.c | 1 + drivers/gpu/drm/nouveau/nouveau_bo.c | 1 + drivers/gpu/drm/qxl/qxl_ttm.c | 1 + drivers/gpu/drm/radeon/radeon_ttm.c | 1 + drivers/gpu/drm/ttm/ttm_bo.c | 35 +++++++++++++++++++++------------ drivers/gpu/drm/virtio/virtgpu_ttm.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 1 + include/drm/ttm/ttm_bo_api.h | 13 ++++++++++++ include/drm/ttm/ttm_bo_driver.h | 12 +++++++++++ 13 files changed, 57 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 414fa8fa8488..fb646c44faae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1109,6 +1109,7 @@ static struct ttm_bo_driver amdgpu_bo_driver = { .ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate, .invalidate_caches = &amdgpu_invalidate_caches, .init_mem_type = &amdgpu_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, .verify_access = &amdgpu_verify_access, diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c index 608df4c90520..7134fdf49210 100644 --- a/drivers/gpu/drm/ast/ast_ttm.c +++ b/drivers/gpu/drm/ast/ast_ttm.c @@ -230,6 +230,7 @@ struct ttm_bo_driver ast_bo_driver = { .ttm_tt_populate = ast_ttm_tt_populate, .ttm_tt_unpopulate = ast_ttm_tt_unpopulate, .init_mem_type = ast_bo_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = ast_bo_evict_flags, .move = NULL, .verify_access = ast_bo_verify_access, diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c index 269cfca9ca06..099a3c688c26 100644 --- a/drivers/gpu/drm/bochs/bochs_mm.c +++ b/drivers/gpu/drm/bochs/bochs_mm.c @@ -199,6 +199,7 @@ struct ttm_bo_driver bochs_bo_driver = { .ttm_tt_populate = ttm_pool_populate, .ttm_tt_unpopulate = ttm_pool_unpopulate, .init_mem_type = bochs_bo_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = bochs_bo_evict_flags, .move = NULL, .verify_access = bochs_bo_verify_access, diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c b/drivers/gpu/drm/cirrus/cirrus_ttm.c index bb2438dd8733..de52b20800e1 100644 --- a/drivers/gpu/drm/cirrus/cirrus_ttm.c +++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c @@ -230,6 +230,7 @@ struct ttm_bo_driver cirrus_bo_driver = { .ttm_tt_populate = cirrus_ttm_tt_populate, .ttm_tt_unpopulate = cirrus_ttm_tt_unpopulate, .init_mem_type = cirrus_bo_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = cirrus_bo_evict_flags, .move = NULL, .verify_access = cirrus_bo_verify_access, diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c index 919b35f2ad24..83272b456329 100644 --- a/drivers/gpu/drm/mgag200/mgag200_ttm.c +++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c @@ -230,6 +230,7 @@ struct ttm_bo_driver mgag200_bo_driver = { .ttm_tt_populate = mgag200_ttm_tt_populate, .ttm_tt_unpopulate = mgag200_ttm_tt_unpopulate, .init_mem_type = mgag200_bo_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = mgag200_bo_evict_flags, .move = NULL, .verify_access = mgag200_bo_verify_access, diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 343b8659472c..e395cb6f511f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1561,6 +1561,7 @@ struct ttm_bo_driver nouveau_bo_driver = { .ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate, .invalidate_caches = nouveau_bo_invalidate_caches, .init_mem_type = nouveau_bo_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = nouveau_bo_evict_flags, .move_notify = nouveau_bo_move_ntfy, .move = nouveau_bo_move, diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index e26c82db948b..11761330a6b8 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -387,6 +387,7 @@ static struct ttm_bo_driver qxl_bo_driver = { .ttm_tt_unpopulate = &qxl_ttm_tt_unpopulate, .invalidate_caches = &qxl_invalidate_caches, .init_mem_type = &qxl_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &qxl_evict_flags, .move = &qxl_bo_move, .verify_access = &qxl_verify_access, diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 3de5e6e21662..0cf03ccbf0a7 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -863,6 +863,7 @@ static struct ttm_bo_driver radeon_bo_driver = { .ttm_tt_unpopulate = &radeon_ttm_tt_unpopulate, .invalidate_caches = &radeon_invalidate_caches, .init_mem_type = &radeon_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &radeon_evict_flags, .move = &radeon_bo_move, .verify_access = &radeon_verify_access, diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index fc6217dfe401..31fcf11a2831 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -717,6 +717,20 @@ out: return ret; } +bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, + const struct ttm_place *place) +{ + /* Don't evict this BO if it's outside of the + * requested placement range + */ + if (place->fpfn >= (bo->mem.start + bo->mem.size) || + (place->lpfn && place->lpfn <= bo->mem.start)) + return false; + + return true; +} +EXPORT_SYMBOL(ttm_bo_eviction_valuable); + static int ttm_mem_evict_first(struct ttm_bo_device *bdev, uint32_t mem_type, const struct ttm_place *place, @@ -731,21 +745,16 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, spin_lock(&glob->lru_lock); list_for_each_entry(bo, &man->lru, lru) { ret = __ttm_bo_reserve(bo, false, true, NULL); - if (!ret) { - if (place && (place->fpfn || place->lpfn)) { - /* Don't evict this BO if it's outside of the - * requested placement range - */ - if (place->fpfn >= (bo->mem.start + bo->mem.size) || - (place->lpfn && place->lpfn <= bo->mem.start)) { - __ttm_bo_unreserve(bo); - ret = -EBUSY; - continue; - } - } + if (ret) + continue; - break; + if (place && !bdev->driver->eviction_valuable(bo, place)) { + __ttm_bo_unreserve(bo); + ret = -EBUSY; + continue; } + + break; } if (ret) { diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c index 80482ac5f95d..4a1de9f81193 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ttm.c +++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c @@ -425,6 +425,7 @@ static struct ttm_bo_driver virtio_gpu_bo_driver = { .ttm_tt_unpopulate = &virtio_gpu_ttm_tt_unpopulate, .invalidate_caches = &virtio_gpu_invalidate_caches, .init_mem_type = &virtio_gpu_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = &virtio_gpu_evict_flags, .move = &virtio_gpu_bo_move, .verify_access = &virtio_gpu_verify_access, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index 78b75ee3c931..c894a48a74a6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -849,6 +849,7 @@ struct ttm_bo_driver vmw_bo_driver = { .ttm_tt_unpopulate = &vmw_ttm_unpopulate, .invalidate_caches = vmw_invalidate_caches, .init_mem_type = vmw_init_mem_type, + .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = vmw_evict_flags, .move = NULL, .verify_access = vmw_verify_access, diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 9eb940d6755f..bb6a3357a817 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -47,6 +47,8 @@ struct drm_mm_node; struct ttm_placement; +struct ttm_place; + /** * struct ttm_bus_placement * @@ -395,6 +397,17 @@ extern int ttm_bo_lock_delayed_workqueue(struct ttm_bo_device *bdev); extern void ttm_bo_unlock_delayed_workqueue(struct ttm_bo_device *bdev, int resched); +/** + * ttm_bo_eviction_valuable + * + * @bo: The buffer object to evict + * @place: the placement we need to make room for + * + * Check if it is valuable to evict the BO to make room for the given placement. + */ +bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, + const struct ttm_place *place); + /** * ttm_bo_synccpu_write_grab * diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 7a76663d4045..d3d83dfe89e2 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -374,6 +374,18 @@ struct ttm_bo_driver { int (*invalidate_caches)(struct ttm_bo_device *bdev, uint32_t flags); int (*init_mem_type)(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man); + + /** + * struct ttm_bo_driver member eviction_valuable + * + * @bo: the buffer object to be evicted + * @place: placement we need room for + * + * Check with the driver if it is valuable to evict a BO to make room + * for a certain placement. + */ + bool (*eviction_valuable)(struct ttm_buffer_object *bo, + const struct ttm_place *place); /** * struct ttm_bo_driver member evict_flags: * -- cgit v1.2.3 From 9982ca681e430907cb7f4e19e2ae4845031d5d59 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 19 Oct 2016 14:44:22 +0200 Subject: drm/amdgpu: add amdgpu_ttm_bo_eviction_valuable callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way we can correctly check split VRAM buffers as well. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index fb646c44faae..f1a206df9823 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1103,13 +1103,37 @@ static struct list_head *amdgpu_ttm_swap_lru_tail(struct ttm_buffer_object *tbo) return res; } +static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, + const struct ttm_place *place) +{ + if (bo->mem.mem_type == TTM_PL_VRAM && + bo->mem.start == AMDGPU_BO_INVALID_OFFSET) { + unsigned long num_pages = bo->mem.num_pages; + struct drm_mm_node *node = bo->mem.mm_node; + + /* Check each drm MM node individually */ + while (num_pages) { + if (place->fpfn < (node->start + node->size) && + !(place->lpfn && place->lpfn <= node->start)) + return true; + + num_pages -= node->size; + ++node; + } + + return false; + } + + return ttm_bo_eviction_valuable(bo, place); +} + static struct ttm_bo_driver amdgpu_bo_driver = { .ttm_tt_create = &amdgpu_ttm_tt_create, .ttm_tt_populate = &amdgpu_ttm_tt_populate, .ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate, .invalidate_caches = &amdgpu_invalidate_caches, .init_mem_type = &amdgpu_init_mem_type, - .eviction_valuable = ttm_bo_eviction_valuable, + .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, .verify_access = &amdgpu_verify_access, -- cgit v1.2.3