Commit 7e5a547f authored by Chunming Zhou's avatar Chunming Zhou Committed by Alex Deucher

drm/amdgpu: implement the allocation range (v3)

Pass a ttm_placement pointer to amdgpu_bo_create_restricted
add min_offset to amdgpu_bo_pin_restricted.  This makes it
easier to allocate memory with address restrictions.  With
this patch we can also enable 2-ended allocation again.

v2: fix rebase conflicts
v3: memset placements before using
Reviewed-by: default avatarJammy Zhou <Jammy.Zhou@amd.com>
Signed-off-by: default avatarChunming Zhou <david1.zhou@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 5fc3aeeb
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <ttm/ttm_execbuf_util.h> #include <ttm/ttm_execbuf_util.h>
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/amdgpu_drm.h>
#include "amd_shared.h" #include "amd_shared.h"
#include "amdgpu_family.h" #include "amdgpu_family.h"
...@@ -542,12 +543,14 @@ struct amdgpu_bo_va { ...@@ -542,12 +543,14 @@ struct amdgpu_bo_va {
struct amdgpu_bo *bo; struct amdgpu_bo *bo;
}; };
#define AMDGPU_GEM_DOMAIN_MAX 0x3
struct amdgpu_bo { struct amdgpu_bo {
/* Protected by gem.mutex */ /* Protected by gem.mutex */
struct list_head list; struct list_head list;
/* Protected by tbo.reserved */ /* Protected by tbo.reserved */
u32 initial_domain; u32 initial_domain;
struct ttm_place placements[4]; struct ttm_place placements[AMDGPU_GEM_DOMAIN_MAX + 1];
struct ttm_placement placement; struct ttm_placement placement;
struct ttm_buffer_object tbo; struct ttm_buffer_object tbo;
struct ttm_bo_kmap_obj kmap; struct ttm_bo_kmap_obj kmap;
......
...@@ -159,7 +159,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc, ...@@ -159,7 +159,7 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
goto cleanup; goto cleanup;
} }
r = amdgpu_bo_pin_restricted(new_rbo, AMDGPU_GEM_DOMAIN_VRAM, 0, &base); r = amdgpu_bo_pin_restricted(new_rbo, AMDGPU_GEM_DOMAIN_VRAM, 0, 0, &base);
if (unlikely(r != 0)) { if (unlikely(r != 0)) {
amdgpu_bo_unreserve(new_rbo); amdgpu_bo_unreserve(new_rbo);
r = -EINVAL; r = -EINVAL;
......
...@@ -150,7 +150,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, ...@@ -150,7 +150,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
} }
ret = amdgpu_bo_pin_restricted(rbo, AMDGPU_GEM_DOMAIN_VRAM, 0, NULL); ret = amdgpu_bo_pin_restricted(rbo, AMDGPU_GEM_DOMAIN_VRAM, 0, 0, NULL);
if (ret) { if (ret) {
amdgpu_bo_unreserve(rbo); amdgpu_bo_unreserve(rbo);
goto out_unref; goto out_unref;
......
...@@ -41,13 +41,13 @@ int amdgpu_ttm_init(struct amdgpu_device *adev); ...@@ -41,13 +41,13 @@ int amdgpu_ttm_init(struct amdgpu_device *adev);
void amdgpu_ttm_fini(struct amdgpu_device *adev); void amdgpu_ttm_fini(struct amdgpu_device *adev);
static u64 amdgpu_get_vis_part_size(struct amdgpu_device *adev, static u64 amdgpu_get_vis_part_size(struct amdgpu_device *adev,
struct ttm_mem_reg * mem) struct ttm_mem_reg *mem)
{ {
u64 ret = 0; u64 ret = 0;
if (mem->start << PAGE_SHIFT < adev->mc.visible_vram_size) { if (mem->start << PAGE_SHIFT < adev->mc.visible_vram_size) {
ret = (u64)((mem->start << PAGE_SHIFT) + mem->size) > ret = (u64)((mem->start << PAGE_SHIFT) + mem->size) >
adev->mc.visible_vram_size ? adev->mc.visible_vram_size ?
adev->mc.visible_vram_size - (mem->start << PAGE_SHIFT): adev->mc.visible_vram_size - (mem->start << PAGE_SHIFT) :
mem->size; mem->size;
} }
return ret; return ret;
...@@ -112,82 +112,111 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo) ...@@ -112,82 +112,111 @@ bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo)
return false; return false;
} }
void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *rbo, u32 domain) static void amdgpu_ttm_placement_init(struct amdgpu_device *adev,
struct ttm_placement *placement,
struct ttm_place *placements,
u32 domain, u64 flags)
{ {
u32 c = 0, i; u32 c = 0, i;
rbo->placement.placement = rbo->placements;
rbo->placement.busy_placement = rbo->placements; placement->placement = placements;
placement->busy_placement = placements;
if (domain & AMDGPU_GEM_DOMAIN_VRAM) { if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
if (rbo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS && if (flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS &&
rbo->adev->mc.visible_vram_size < rbo->adev->mc.real_vram_size) { adev->mc.visible_vram_size < adev->mc.real_vram_size) {
rbo->placements[c].fpfn = placements[c].fpfn =
rbo->adev->mc.visible_vram_size >> PAGE_SHIFT; adev->mc.visible_vram_size >> PAGE_SHIFT;
rbo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_VRAM; TTM_PL_FLAG_VRAM;
} }
rbo->placements[c].fpfn = 0; placements[c].fpfn = 0;
rbo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_VRAM; TTM_PL_FLAG_VRAM;
} }
if (domain & AMDGPU_GEM_DOMAIN_GTT) { if (domain & AMDGPU_GEM_DOMAIN_GTT) {
if (rbo->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) { if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) {
rbo->placements[c].fpfn = 0; placements[c].fpfn = 0;
rbo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT | placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT |
TTM_PL_FLAG_UNCACHED; TTM_PL_FLAG_UNCACHED;
} else { } else {
rbo->placements[c].fpfn = 0; placements[c].fpfn = 0;
rbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT;
} }
} }
if (domain & AMDGPU_GEM_DOMAIN_CPU) { if (domain & AMDGPU_GEM_DOMAIN_CPU) {
if (rbo->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) { if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) {
rbo->placements[c].fpfn = 0; placements[c].fpfn = 0;
rbo->placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_SYSTEM | placements[c++].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_SYSTEM |
TTM_PL_FLAG_UNCACHED; TTM_PL_FLAG_UNCACHED;
} else { } else {
rbo->placements[c].fpfn = 0; placements[c].fpfn = 0;
rbo->placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM; placements[c++].flags = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM;
} }
} }
if (domain & AMDGPU_GEM_DOMAIN_GDS) { if (domain & AMDGPU_GEM_DOMAIN_GDS) {
rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED | placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_UNCACHED |
AMDGPU_PL_FLAG_GDS; AMDGPU_PL_FLAG_GDS;
} }
if (domain & AMDGPU_GEM_DOMAIN_GWS) { if (domain & AMDGPU_GEM_DOMAIN_GWS) {
rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED | placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_UNCACHED |
AMDGPU_PL_FLAG_GWS; AMDGPU_PL_FLAG_GWS;
} }
if (domain & AMDGPU_GEM_DOMAIN_OA) { if (domain & AMDGPU_GEM_DOMAIN_OA) {
rbo->placements[c++].flags = TTM_PL_FLAG_UNCACHED | placements[c].fpfn = 0;
placements[c++].flags = TTM_PL_FLAG_UNCACHED |
AMDGPU_PL_FLAG_OA; AMDGPU_PL_FLAG_OA;
} }
if (!c) { if (!c) {
rbo->placements[c].fpfn = 0; placements[c].fpfn = 0;
rbo->placements[c++].flags = TTM_PL_MASK_CACHING | placements[c++].flags = TTM_PL_MASK_CACHING |
TTM_PL_FLAG_SYSTEM; TTM_PL_FLAG_SYSTEM;
} }
rbo->placement.num_placement = c; placement->num_placement = c;
rbo->placement.num_busy_placement = c; placement->num_busy_placement = c;
for (i = 0; i < c; i++) { for (i = 0; i < c; i++) {
if ((rbo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) && if ((flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
(rbo->placements[i].flags & TTM_PL_FLAG_VRAM) && (placements[i].flags & TTM_PL_FLAG_VRAM) &&
!rbo->placements[i].fpfn) !placements[i].fpfn)
rbo->placements[i].lpfn = placements[i].lpfn =
rbo->adev->mc.visible_vram_size >> PAGE_SHIFT; adev->mc.visible_vram_size >> PAGE_SHIFT;
else else
rbo->placements[i].lpfn = 0; placements[i].lpfn = 0;
} }
} }
int amdgpu_bo_create(struct amdgpu_device *adev, void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *rbo, u32 domain)
unsigned long size, int byte_align, bool kernel, u32 domain, u64 flags, {
struct sg_table *sg, struct amdgpu_bo **bo_ptr) amdgpu_ttm_placement_init(rbo->adev, &rbo->placement,
rbo->placements, domain, rbo->flags);
}
static void amdgpu_fill_placement_to_bo(struct amdgpu_bo *bo,
struct ttm_placement *placement)
{
BUG_ON(placement->num_placement > (AMDGPU_GEM_DOMAIN_MAX + 1));
memcpy(bo->placements, placement->placement,
placement->num_placement * sizeof(struct ttm_place));
bo->placement.num_placement = placement->num_placement;
bo->placement.num_busy_placement = placement->num_busy_placement;
bo->placement.placement = bo->placements;
bo->placement.busy_placement = bo->placements;
}
int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
unsigned long size, int byte_align,
bool kernel, u32 domain, u64 flags,
struct sg_table *sg,
struct ttm_placement *placement,
struct amdgpu_bo **bo_ptr)
{ {
struct amdgpu_bo *bo; struct amdgpu_bo *bo;
enum ttm_bo_type type; enum ttm_bo_type type;
...@@ -241,7 +270,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, ...@@ -241,7 +270,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
AMDGPU_GEM_DOMAIN_OA); AMDGPU_GEM_DOMAIN_OA);
bo->flags = flags; bo->flags = flags;
amdgpu_ttm_placement_from_domain(bo, domain); amdgpu_fill_placement_to_bo(bo, placement);
/* Kernel allocation are uninterruptible */ /* Kernel allocation are uninterruptible */
down_read(&adev->pm.mclk_lock); down_read(&adev->pm.mclk_lock);
r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type, r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type,
...@@ -258,6 +287,27 @@ int amdgpu_bo_create(struct amdgpu_device *adev, ...@@ -258,6 +287,27 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
return 0; return 0;
} }
int amdgpu_bo_create(struct amdgpu_device *adev,
unsigned long size, int byte_align,
bool kernel, u32 domain, u64 flags,
struct sg_table *sg, struct amdgpu_bo **bo_ptr)
{
struct ttm_placement placement = {0};
struct ttm_place placements[AMDGPU_GEM_DOMAIN_MAX + 1];
memset(&placements, 0,
(AMDGPU_GEM_DOMAIN_MAX + 1) * sizeof(struct ttm_place));
amdgpu_ttm_placement_init(adev, &placement,
placements, domain, flags);
return amdgpu_bo_create_restricted(adev, size, byte_align,
kernel, domain, flags,
sg,
&placement,
bo_ptr);
}
int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr) int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
{ {
bool is_iomem; bool is_iomem;
...@@ -313,14 +363,19 @@ void amdgpu_bo_unref(struct amdgpu_bo **bo) ...@@ -313,14 +363,19 @@ void amdgpu_bo_unref(struct amdgpu_bo **bo)
*bo = NULL; *bo = NULL;
} }
int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 max_offset, int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
u64 min_offset, u64 max_offset,
u64 *gpu_addr) u64 *gpu_addr)
{ {
int r, i; int r, i;
unsigned fpfn, lpfn;
if (amdgpu_ttm_tt_has_userptr(bo->tbo.ttm)) if (amdgpu_ttm_tt_has_userptr(bo->tbo.ttm))
return -EPERM; return -EPERM;
if (WARN_ON_ONCE(min_offset > max_offset))
return -EINVAL;
if (bo->pin_count) { if (bo->pin_count) {
bo->pin_count++; bo->pin_count++;
if (gpu_addr) if (gpu_addr)
...@@ -328,7 +383,6 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 max_offset, ...@@ -328,7 +383,6 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 max_offset,
if (max_offset != 0) { if (max_offset != 0) {
u64 domain_start; u64 domain_start;
if (domain == AMDGPU_GEM_DOMAIN_VRAM) if (domain == AMDGPU_GEM_DOMAIN_VRAM)
domain_start = bo->adev->mc.vram_start; domain_start = bo->adev->mc.vram_start;
else else
...@@ -344,12 +398,20 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 max_offset, ...@@ -344,12 +398,20 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 max_offset,
/* force to pin into visible video ram */ /* force to pin into visible video ram */
if ((bo->placements[i].flags & TTM_PL_FLAG_VRAM) && if ((bo->placements[i].flags & TTM_PL_FLAG_VRAM) &&
!(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) && !(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) &&
(!max_offset || max_offset > bo->adev->mc.visible_vram_size)) (!max_offset || max_offset > bo->adev->mc.visible_vram_size)) {
bo->placements[i].lpfn = if (WARN_ON_ONCE(min_offset >
bo->adev->mc.visible_vram_size >> PAGE_SHIFT; bo->adev->mc.visible_vram_size))
else return -EINVAL;
bo->placements[i].lpfn = max_offset >> PAGE_SHIFT; fpfn = min_offset >> PAGE_SHIFT;
lpfn = bo->adev->mc.visible_vram_size >> PAGE_SHIFT;
} else {
fpfn = min_offset >> PAGE_SHIFT;
lpfn = max_offset >> PAGE_SHIFT;
}
if (fpfn > bo->placements[i].fpfn)
bo->placements[i].fpfn = fpfn;
if (lpfn && lpfn < bo->placements[i].lpfn)
bo->placements[i].lpfn = lpfn;
bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
} }
...@@ -370,7 +432,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 max_offset, ...@@ -370,7 +432,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 max_offset,
int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain, u64 *gpu_addr) int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain, u64 *gpu_addr)
{ {
return amdgpu_bo_pin_restricted(bo, domain, 0, gpu_addr); return amdgpu_bo_pin_restricted(bo, domain, 0, 0, gpu_addr);
} }
int amdgpu_bo_unpin(struct amdgpu_bo *bo) int amdgpu_bo_unpin(struct amdgpu_bo *bo)
......
...@@ -130,13 +130,20 @@ int amdgpu_bo_create(struct amdgpu_device *adev, ...@@ -130,13 +130,20 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
bool kernel, u32 domain, u64 flags, bool kernel, u32 domain, u64 flags,
struct sg_table *sg, struct sg_table *sg,
struct amdgpu_bo **bo_ptr); struct amdgpu_bo **bo_ptr);
int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
unsigned long size, int byte_align,
bool kernel, u32 domain, u64 flags,
struct sg_table *sg,
struct ttm_placement *placement,
struct amdgpu_bo **bo_ptr);
int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr); int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr);
void amdgpu_bo_kunmap(struct amdgpu_bo *bo); void amdgpu_bo_kunmap(struct amdgpu_bo *bo);
struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo); struct amdgpu_bo *amdgpu_bo_ref(struct amdgpu_bo *bo);
void amdgpu_bo_unref(struct amdgpu_bo **bo); void amdgpu_bo_unref(struct amdgpu_bo **bo);
int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain, u64 *gpu_addr); int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain, u64 *gpu_addr);
int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
u64 max_offset, u64 *gpu_addr); u64 min_offset, u64 max_offset,
u64 *gpu_addr);
int amdgpu_bo_unpin(struct amdgpu_bo *bo); int amdgpu_bo_unpin(struct amdgpu_bo *bo);
int amdgpu_bo_evict_vram(struct amdgpu_device *adev); int amdgpu_bo_evict_vram(struct amdgpu_device *adev);
void amdgpu_bo_force_delete(struct amdgpu_device *adev); void amdgpu_bo_force_delete(struct amdgpu_device *adev);
......
...@@ -2553,7 +2553,7 @@ static int dce_v10_0_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -2553,7 +2553,7 @@ static int dce_v10_0_crtc_cursor_set(struct drm_crtc *crtc,
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto fail; goto fail;
ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM,
0, &gpu_addr); 0, 0, &gpu_addr);
amdgpu_bo_unreserve(robj); amdgpu_bo_unreserve(robj);
if (ret) if (ret)
goto fail; goto fail;
......
...@@ -2552,7 +2552,7 @@ static int dce_v11_0_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -2552,7 +2552,7 @@ static int dce_v11_0_crtc_cursor_set(struct drm_crtc *crtc,
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto fail; goto fail;
ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM,
0, &gpu_addr); 0, 0, &gpu_addr);
amdgpu_bo_unreserve(robj); amdgpu_bo_unreserve(robj);
if (ret) if (ret)
goto fail; goto fail;
......
...@@ -2496,7 +2496,7 @@ static int dce_v8_0_crtc_cursor_set(struct drm_crtc *crtc, ...@@ -2496,7 +2496,7 @@ static int dce_v8_0_crtc_cursor_set(struct drm_crtc *crtc,
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto fail; goto fail;
ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM,
0, &gpu_addr); 0, 0, &gpu_addr);
amdgpu_bo_unreserve(robj); amdgpu_bo_unreserve(robj);
if (ret) if (ret)
goto fail; goto fail;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment