Arunpravin Paneer Selvam
2022-Jul-20 07:41 UTC
[Nouveau] [PATCH 1/4] drm/ttm: add new intersect callback to res mgr
- This allows the resource manager to handle intersection of placement and resources. - Add callback function to amdgpu driver module fetching start offset from buddy allocator. Signed-off-by: Christian K?nig <christian.koenig at amd.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam at amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 19 +++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 33 ++++++++++++++++++++ drivers/gpu/drm/ttm/ttm_range_manager.c | 17 ++++++++++ drivers/gpu/drm/ttm/ttm_resource.c | 28 +++++++++++++++++ include/drm/ttm/ttm_resource.h | 20 ++++++++++++ 5 files changed, 117 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 8c6b2284cf56..727c80134aa6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -204,6 +204,24 @@ void amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr) amdgpu_gart_invalidate_tlb(adev); } +/** + * amdgpu_gtt_mgr_intersect - test for intersection + * + * @man: Our manager object + * @res: The resource to test + * @place: The place for the new allocation + * @size: The size of the new allocation + * + * Simplified intersection test, only interesting if we need GART or not. + */ +static bool amdgpu_gtt_mgr_intersect(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res); +} + /** * amdgpu_gtt_mgr_debug - dump VRAM table * @@ -225,6 +243,7 @@ static void amdgpu_gtt_mgr_debug(struct ttm_resource_manager *man, static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func = { .alloc = amdgpu_gtt_mgr_new, .free = amdgpu_gtt_mgr_del, + .intersect = amdgpu_gtt_mgr_intersect, .debug = amdgpu_gtt_mgr_debug }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 28ec5f8ac1c1..ed0d10fe0b88 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -720,6 +720,38 @@ uint64_t amdgpu_vram_mgr_vis_usage(struct amdgpu_vram_mgr *mgr) return atomic64_read(&mgr->vis_usage); } +/** + * amdgpu_vram_mgr_intersect - test each drm buddy block for intersection + * + * @man: TTM memory type manager + * @res: The resource to test + * @place: The place to test against + * @size: Size of the new allocation + * + * Test each drm buddy block for intersection for eviction decision. + */ +static bool amdgpu_vram_mgr_intersect(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct amdgpu_vram_mgr_resource *mgr = to_amdgpu_vram_mgr_resource(res); + struct list_head *list = &mgr->blocks; + struct drm_buddy_block *block; + u32 num_pages = PFN_UP(size); + u32 start; + + /* Check each drm buddy block individually */ + list_for_each_entry(block, list, link) { + start = amdgpu_vram_mgr_block_start(block) >> PAGE_SHIFT; + if (start < place->fpfn || + (place->lpfn && (start + num_pages) > place->lpfn)) + return false; + } + + return true; +} + /** * amdgpu_vram_mgr_debug - dump VRAM table * @@ -753,6 +785,7 @@ static void amdgpu_vram_mgr_debug(struct ttm_resource_manager *man, static const struct ttm_resource_manager_func amdgpu_vram_mgr_func = { .alloc = amdgpu_vram_mgr_new, .free = amdgpu_vram_mgr_del, + .intersect = amdgpu_vram_mgr_intersect, .debug = amdgpu_vram_mgr_debug }; diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c index d91666721dc6..bf5de1978ead 100644 --- a/drivers/gpu/drm/ttm/ttm_range_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -113,6 +113,22 @@ static void ttm_range_man_free(struct ttm_resource_manager *man, kfree(node); } +static bool ttm_range_man_intersect(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct drm_mm_node *node = &to_ttm_range_mgr_node(res)->mm_nodes[0]; + u32 num_pages = PFN_UP(size); + + /* Don't evict BOs outside of the requested placement range */ + if (place->fpfn >= (node->start + num_pages) || + (place->lpfn && place->lpfn <= node->start)) + return false; + + return true; +} + static void ttm_range_man_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { @@ -126,6 +142,7 @@ static void ttm_range_man_debug(struct ttm_resource_manager *man, static const struct ttm_resource_manager_func ttm_range_manager_func = { .alloc = ttm_range_man_alloc, .free = ttm_range_man_free, + .intersect = ttm_range_man_intersect, .debug = ttm_range_man_debug }; diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 20f9adcc3235..84c21f92b422 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -253,6 +253,34 @@ void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res) } EXPORT_SYMBOL(ttm_resource_free); +/** + * ttm_resource_intersect - test for intersection + * + * @bdev: TTM device structure + * @res: The resource to test + * @place: The placement to test + * @size: How many bytes the new allocation needs. + * + * Test if @res intersects with @place and @size. Used for testing if evictions + * are valueable or not. + */ +bool ttm_resource_intersect(struct ttm_device *bdev, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct ttm_resource_manager *man; + + if (!res) + return false; + + man = ttm_manager_type(bdev, res->mem_type); + if (!place || !man->func->intersect) + return true; + + return man->func->intersect(man, res, place, size); +} + static bool ttm_resource_places_compat(struct ttm_resource *res, const struct ttm_place *places, unsigned num_placement) diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index ca89a48c2460..3f3ab2a8a69e 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -88,6 +88,22 @@ struct ttm_resource_manager_func { void (*free)(struct ttm_resource_manager *man, struct ttm_resource *res); + /** + * struct ttm_resource_manager_func member intersect + * + * @man: Pointer to a memory type manager. + * @res: Pointer to a struct ttm_resource to be checked. + * @place: Placement to check against. + * @size: Size of the check. + * + * Test if @res intersects with @place + @size. Used to judge if + * evictions are valueable or not. + */ + bool (*intersect)(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size); + /** * struct ttm_resource_manager_func member debug * @@ -329,6 +345,10 @@ int ttm_resource_alloc(struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_resource **res); void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res); +bool ttm_resource_intersect(struct ttm_device *bdev, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size); bool ttm_resource_compat(struct ttm_resource *res, struct ttm_placement *placement); void ttm_resource_set_bo(struct ttm_resource *res, -- 2.25.1
Arunpravin Paneer Selvam
2022-Jul-20 07:41 UTC
[Nouveau] [PATCH 2/4] drm/i915: Add intersect callback function
Add a new intersect callback function fetching start offset from backend drm buddy allocator. Signed-off-by: Christian K?nig <christian.koenig at amd.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam at amd.com> --- drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c index a5109548abc0..30bb8ade67a9 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c @@ -178,6 +178,28 @@ static void i915_ttm_buddy_man_free(struct ttm_resource_manager *man, kfree(bman_res); } +static bool i915_ttm_buddy_man_intersect(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res); + struct list_head *list = &bman_res->blocks; + struct drm_buddy_block *block; + u32 num_pages = PFN_UP(size); + u32 start; + + /* Check each drm buddy block individually */ + list_for_each_entry(block, list, link) { + start = drm_buddy_block_offset(block) >> PAGE_SHIFT; + if (start < place->fpfn || + (place->lpfn && (start + num_pages) > place->lpfn)) + return false; + } + + return true; +} + static void i915_ttm_buddy_man_debug(struct ttm_resource_manager *man, struct drm_printer *printer) { @@ -205,6 +227,7 @@ static void i915_ttm_buddy_man_debug(struct ttm_resource_manager *man, static const struct ttm_resource_manager_func i915_ttm_buddy_manager_func = { .alloc = i915_ttm_buddy_man_alloc, .free = i915_ttm_buddy_man_free, + .intersect = i915_ttm_buddy_man_intersect, .debug = i915_ttm_buddy_man_debug, }; -- 2.25.1
Arunpravin Paneer Selvam
2022-Jul-20 07:41 UTC
[Nouveau] [PATCH 3/4] drm/nouveau: Add intersect callback function
Add a new intersect callback function fetching the start offset from struct ttm_resource. Signed-off-by: Christian K?nig <christian.koenig at amd.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam at amd.com> --- drivers/gpu/drm/nouveau/nouveau_mem.c | 15 +++++++++++++++ drivers/gpu/drm/nouveau/nouveau_mem.h | 3 +++ drivers/gpu/drm/nouveau/nouveau_ttm.c | 12 ++++++++++++ 3 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 2e517cdc24c9..b8a773f03c32 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -187,3 +187,18 @@ nouveau_mem_new(struct nouveau_cli *cli, u8 kind, u8 comp, *res = &mem->base; return 0; } + +bool +nouveau_mem_intersect(struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + u32 num_pages = PFN_UP(size); + + /* Don't evict BOs outside of the requested placement range */ + if (place->fpfn >= (res->start + num_pages) || + (place->lpfn && place->lpfn <= res->start)) + return false; + + return true; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.h b/drivers/gpu/drm/nouveau/nouveau_mem.h index 325551eba5cd..349fefe48e3c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.h +++ b/drivers/gpu/drm/nouveau/nouveau_mem.h @@ -25,6 +25,9 @@ int nouveau_mem_new(struct nouveau_cli *, u8 kind, u8 comp, struct ttm_resource **); void nouveau_mem_del(struct ttm_resource_manager *man, struct ttm_resource *); +bool nouveau_mem_intersect(struct ttm_resource *res, + const struct ttm_place *place, + size_t size); int nouveau_mem_vram(struct ttm_resource *, bool contig, u8 page); int nouveau_mem_host(struct ttm_resource *, struct ttm_tt *); void nouveau_mem_fini(struct nouveau_mem *); diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 85f1f5a0fe5d..46afd57008dd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -42,6 +42,15 @@ nouveau_manager_del(struct ttm_resource_manager *man, nouveau_mem_del(man, reg); } +static bool +nouveau_manager_intersect(struct ttm_resource_manager *man, + struct ttm_resource *res, + const struct ttm_place *place, + size_t size) +{ + return nouveau_mem_intersect(res, place, size); +} + static int nouveau_vram_manager_new(struct ttm_resource_manager *man, struct ttm_buffer_object *bo, @@ -73,6 +82,7 @@ nouveau_vram_manager_new(struct ttm_resource_manager *man, const struct ttm_resource_manager_func nouveau_vram_manager = { .alloc = nouveau_vram_manager_new, .free = nouveau_manager_del, + .intersect = nouveau_manager_intersect, }; static int @@ -97,6 +107,7 @@ nouveau_gart_manager_new(struct ttm_resource_manager *man, const struct ttm_resource_manager_func nouveau_gart_manager = { .alloc = nouveau_gart_manager_new, .free = nouveau_manager_del, + .intersect = nouveau_manager_intersect, }; static int @@ -130,6 +141,7 @@ nv04_gart_manager_new(struct ttm_resource_manager *man, const struct ttm_resource_manager_func nv04_gart_manager = { .alloc = nv04_gart_manager_new, .free = nouveau_manager_del, + .intersect = nouveau_manager_intersect, }; static int -- 2.25.1
Arunpravin Paneer Selvam
2022-Jul-20 07:41 UTC
[Nouveau] [PATCH 4/4] drm/ttm: Switch to using the new intersect callback
Use new intersect callback instead of having a generic placement range verification. Signed-off-by: Christian K?nig <christian.koenig at amd.com> Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam at amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 45 +++++++------------------ drivers/gpu/drm/ttm/ttm_bo.c | 9 +++-- drivers/gpu/drm/ttm/ttm_resource.c | 5 +-- 3 files changed, 20 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 170935c294f5..7d25a10395c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1328,11 +1328,12 @@ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place) { - unsigned long num_pages = bo->resource->num_pages; struct dma_resv_iter resv_cursor; - struct amdgpu_res_cursor cursor; struct dma_fence *f; + if (!amdgpu_bo_is_amdgpu_bo(bo)) + return ttm_bo_eviction_valuable(bo, place); + /* Swapout? */ if (bo->resource->mem_type == TTM_PL_SYSTEM) return true; @@ -1351,40 +1352,20 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, return false; } - switch (bo->resource->mem_type) { - case AMDGPU_PL_PREEMPT: - /* Preemptible BOs don't own system resources managed by the - * driver (pages, VRAM, GART space). They point to resources - * owned by someone else (e.g. pageable memory in user mode - * or a DMABuf). They are used in a preemptible context so we - * can guarantee no deadlocks and good QoS in case of MMU - * notifiers or DMABuf move notifiers from the resource owner. - */ + /* Preemptible BOs don't own system resources managed by the + * driver (pages, VRAM, GART space). They point to resources + * owned by someone else (e.g. pageable memory in user mode + * or a DMABuf). They are used in a preemptible context so we + * can guarantee no deadlocks and good QoS in case of MMU + * notifiers or DMABuf move notifiers from the resource owner. + */ + if (bo->resource->mem_type == AMDGPU_PL_PREEMPT) return false; - case TTM_PL_TT: - if (amdgpu_bo_is_amdgpu_bo(bo) && - amdgpu_bo_encrypted(ttm_to_amdgpu_bo(bo))) - return false; - return true; - case TTM_PL_VRAM: - /* Check each drm MM node individually */ - amdgpu_res_first(bo->resource, 0, (u64)num_pages << PAGE_SHIFT, - &cursor); - while (cursor.remaining) { - if (place->fpfn < PFN_DOWN(cursor.start + cursor.size) - && !(place->lpfn && - place->lpfn <= PFN_DOWN(cursor.start))) - return true; - - amdgpu_res_next(&cursor, cursor.size); - } + if (bo->resource->mem_type == TTM_PL_TT && + amdgpu_bo_encrypted(ttm_to_amdgpu_bo(bo))) return false; - default: - break; - } - return ttm_bo_eviction_valuable(bo, place); } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index c1bd006a5525..03409409e43e 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -518,6 +518,9 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place) { + struct ttm_resource *res = bo->resource; + struct ttm_device *bdev = bo->bdev; + dma_resv_assert_held(bo->base.resv); if (bo->resource->mem_type == TTM_PL_SYSTEM) return true; @@ -525,11 +528,7 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, /* Don't evict this BO if it's outside of the * requested placement range */ - if (place->fpfn >= (bo->resource->start + bo->resource->num_pages) || - (place->lpfn && place->lpfn <= bo->resource->start)) - return false; - - return true; + return ttm_resource_intersect(bdev, res, place, bo->base.size); } EXPORT_SYMBOL(ttm_bo_eviction_valuable); diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 84c21f92b422..ff3e9058943c 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -285,6 +285,8 @@ static bool ttm_resource_places_compat(struct ttm_resource *res, const struct ttm_place *places, unsigned num_placement) { + struct ttm_buffer_object *bo = res->bo; + struct ttm_device *bdev = bo->bdev; unsigned i; if (res->placement & TTM_PL_FLAG_TEMPORARY) @@ -293,8 +295,7 @@ static bool ttm_resource_places_compat(struct ttm_resource *res, for (i = 0; i < num_placement; i++) { const struct ttm_place *heap = &places[i]; - if (res->start < heap->fpfn || (heap->lpfn && - (res->start + res->num_pages) > heap->lpfn)) + if (!ttm_resource_intersect(bdev, res, heap, bo->base.size)) continue; if ((res->mem_type == heap->mem_type) && -- 2.25.1
Christian König
2022-Jul-20 08:41 UTC
[Nouveau] [PATCH 1/4] drm/ttm: add new intersect callback to res mgr
Am 20.07.22 um 09:36 schrieb Arunpravin Paneer Selvam:> - This allows the resource manager to handle intersection > of placement and resources. > > - Add callback function to amdgpu driver module fetching > start offset from buddy allocator.Probably better to only add the callback and ttm_resource_intersect() wrapper function in this patch and then move the amdgpu and ttm_range_manager changes to separate patches. Apart from that looks good to me. Regards, Christian.> > Signed-off-by: Christian K?nig <christian.koenig at amd.com> > Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam at amd.com> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 19 +++++++++++ > drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 33 ++++++++++++++++++++ > drivers/gpu/drm/ttm/ttm_range_manager.c | 17 ++++++++++ > drivers/gpu/drm/ttm/ttm_resource.c | 28 +++++++++++++++++ > include/drm/ttm/ttm_resource.h | 20 ++++++++++++ > 5 files changed, 117 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c > index 8c6b2284cf56..727c80134aa6 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c > @@ -204,6 +204,24 @@ void amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr) > amdgpu_gart_invalidate_tlb(adev); > } > > +/** > + * amdgpu_gtt_mgr_intersect - test for intersection > + * > + * @man: Our manager object > + * @res: The resource to test > + * @place: The place for the new allocation > + * @size: The size of the new allocation > + * > + * Simplified intersection test, only interesting if we need GART or not. > + */ > +static bool amdgpu_gtt_mgr_intersect(struct ttm_resource_manager *man, > + struct ttm_resource *res, > + const struct ttm_place *place, > + size_t size) > +{ > + return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res); > +} > + > /** > * amdgpu_gtt_mgr_debug - dump VRAM table > * > @@ -225,6 +243,7 @@ static void amdgpu_gtt_mgr_debug(struct ttm_resource_manager *man, > static const struct ttm_resource_manager_func amdgpu_gtt_mgr_func = { > .alloc = amdgpu_gtt_mgr_new, > .free = amdgpu_gtt_mgr_del, > + .intersect = amdgpu_gtt_mgr_intersect, > .debug = amdgpu_gtt_mgr_debug > }; > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c > index 28ec5f8ac1c1..ed0d10fe0b88 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c > @@ -720,6 +720,38 @@ uint64_t amdgpu_vram_mgr_vis_usage(struct amdgpu_vram_mgr *mgr) > return atomic64_read(&mgr->vis_usage); > } > > +/** > + * amdgpu_vram_mgr_intersect - test each drm buddy block for intersection > + * > + * @man: TTM memory type manager > + * @res: The resource to test > + * @place: The place to test against > + * @size: Size of the new allocation > + * > + * Test each drm buddy block for intersection for eviction decision. > + */ > +static bool amdgpu_vram_mgr_intersect(struct ttm_resource_manager *man, > + struct ttm_resource *res, > + const struct ttm_place *place, > + size_t size) > +{ > + struct amdgpu_vram_mgr_resource *mgr = to_amdgpu_vram_mgr_resource(res); > + struct list_head *list = &mgr->blocks; > + struct drm_buddy_block *block; > + u32 num_pages = PFN_UP(size); > + u32 start; > + > + /* Check each drm buddy block individually */ > + list_for_each_entry(block, list, link) { > + start = amdgpu_vram_mgr_block_start(block) >> PAGE_SHIFT; > + if (start < place->fpfn || > + (place->lpfn && (start + num_pages) > place->lpfn)) > + return false; > + } > + > + return true; > +} > + > /** > * amdgpu_vram_mgr_debug - dump VRAM table > * > @@ -753,6 +785,7 @@ static void amdgpu_vram_mgr_debug(struct ttm_resource_manager *man, > static const struct ttm_resource_manager_func amdgpu_vram_mgr_func = { > .alloc = amdgpu_vram_mgr_new, > .free = amdgpu_vram_mgr_del, > + .intersect = amdgpu_vram_mgr_intersect, > .debug = amdgpu_vram_mgr_debug > }; > > diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c > index d91666721dc6..bf5de1978ead 100644 > --- a/drivers/gpu/drm/ttm/ttm_range_manager.c > +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c > @@ -113,6 +113,22 @@ static void ttm_range_man_free(struct ttm_resource_manager *man, > kfree(node); > } > > +static bool ttm_range_man_intersect(struct ttm_resource_manager *man, > + struct ttm_resource *res, > + const struct ttm_place *place, > + size_t size) > +{ > + struct drm_mm_node *node = &to_ttm_range_mgr_node(res)->mm_nodes[0]; > + u32 num_pages = PFN_UP(size); > + > + /* Don't evict BOs outside of the requested placement range */ > + if (place->fpfn >= (node->start + num_pages) || > + (place->lpfn && place->lpfn <= node->start)) > + return false; > + > + return true; > +} > + > static void ttm_range_man_debug(struct ttm_resource_manager *man, > struct drm_printer *printer) > { > @@ -126,6 +142,7 @@ static void ttm_range_man_debug(struct ttm_resource_manager *man, > static const struct ttm_resource_manager_func ttm_range_manager_func = { > .alloc = ttm_range_man_alloc, > .free = ttm_range_man_free, > + .intersect = ttm_range_man_intersect, > .debug = ttm_range_man_debug > }; > > diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c > index 20f9adcc3235..84c21f92b422 100644 > --- a/drivers/gpu/drm/ttm/ttm_resource.c > +++ b/drivers/gpu/drm/ttm/ttm_resource.c > @@ -253,6 +253,34 @@ void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res) > } > EXPORT_SYMBOL(ttm_resource_free); > > +/** > + * ttm_resource_intersect - test for intersection > + * > + * @bdev: TTM device structure > + * @res: The resource to test > + * @place: The placement to test > + * @size: How many bytes the new allocation needs. > + * > + * Test if @res intersects with @place and @size. Used for testing if evictions > + * are valueable or not. > + */ > +bool ttm_resource_intersect(struct ttm_device *bdev, > + struct ttm_resource *res, > + const struct ttm_place *place, > + size_t size) > +{ > + struct ttm_resource_manager *man; > + > + if (!res) > + return false; > + > + man = ttm_manager_type(bdev, res->mem_type); > + if (!place || !man->func->intersect) > + return true; > + > + return man->func->intersect(man, res, place, size); > +} > + > static bool ttm_resource_places_compat(struct ttm_resource *res, > const struct ttm_place *places, > unsigned num_placement) > diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h > index ca89a48c2460..3f3ab2a8a69e 100644 > --- a/include/drm/ttm/ttm_resource.h > +++ b/include/drm/ttm/ttm_resource.h > @@ -88,6 +88,22 @@ struct ttm_resource_manager_func { > void (*free)(struct ttm_resource_manager *man, > struct ttm_resource *res); > > + /** > + * struct ttm_resource_manager_func member intersect > + * > + * @man: Pointer to a memory type manager. > + * @res: Pointer to a struct ttm_resource to be checked. > + * @place: Placement to check against. > + * @size: Size of the check. > + * > + * Test if @res intersects with @place + @size. Used to judge if > + * evictions are valueable or not. > + */ > + bool (*intersect)(struct ttm_resource_manager *man, > + struct ttm_resource *res, > + const struct ttm_place *place, > + size_t size); > + > /** > * struct ttm_resource_manager_func member debug > * > @@ -329,6 +345,10 @@ int ttm_resource_alloc(struct ttm_buffer_object *bo, > const struct ttm_place *place, > struct ttm_resource **res); > void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res); > +bool ttm_resource_intersect(struct ttm_device *bdev, > + struct ttm_resource *res, > + const struct ttm_place *place, > + size_t size); > bool ttm_resource_compat(struct ttm_resource *res, > struct ttm_placement *placement); > void ttm_resource_set_bo(struct ttm_resource *res,
Christian König
2022-Jul-20 08:44 UTC
[Nouveau] [PATCH 4/4] drm/ttm: Switch to using the new intersect callback
Am 20.07.22 um 09:36 schrieb Arunpravin Paneer Selvam:> Use new intersect callback instead of having a generic > placement range verification. > > Signed-off-by: Christian K?nig <christian.koenig at amd.com> > Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam at amd.com> > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 45 +++++++------------------ > drivers/gpu/drm/ttm/ttm_bo.c | 9 +++-- > drivers/gpu/drm/ttm/ttm_resource.c | 5 +-- > 3 files changed, 20 insertions(+), 39 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c > index 170935c294f5..7d25a10395c0 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c > @@ -1328,11 +1328,12 @@ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, > static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, > const struct ttm_place *place) > { > - unsigned long num_pages = bo->resource->num_pages; > struct dma_resv_iter resv_cursor; > - struct amdgpu_res_cursor cursor; > struct dma_fence *f; > > + if (!amdgpu_bo_is_amdgpu_bo(bo)) > + return ttm_bo_eviction_valuable(bo, place); > + > /* Swapout? */ > if (bo->resource->mem_type == TTM_PL_SYSTEM) > return true; > @@ -1351,40 +1352,20 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, > return false; > } > > - switch (bo->resource->mem_type) { > - case AMDGPU_PL_PREEMPT: > - /* Preemptible BOs don't own system resources managed by the > - * driver (pages, VRAM, GART space). They point to resources > - * owned by someone else (e.g. pageable memory in user mode > - * or a DMABuf). They are used in a preemptible context so we > - * can guarantee no deadlocks and good QoS in case of MMU > - * notifiers or DMABuf move notifiers from the resource owner. > - */ > + /* Preemptible BOs don't own system resources managed by the > + * driver (pages, VRAM, GART space). They point to resources > + * owned by someone else (e.g. pageable memory in user mode > + * or a DMABuf). They are used in a preemptible context so we > + * can guarantee no deadlocks and good QoS in case of MMU > + * notifiers or DMABuf move notifiers from the resource owner. > + */ > + if (bo->resource->mem_type == AMDGPU_PL_PREEMPT) > return false; > - case TTM_PL_TT: > - if (amdgpu_bo_is_amdgpu_bo(bo) && > - amdgpu_bo_encrypted(ttm_to_amdgpu_bo(bo))) > - return false; > - return true; > > - case TTM_PL_VRAM: > - /* Check each drm MM node individually */ > - amdgpu_res_first(bo->resource, 0, (u64)num_pages << PAGE_SHIFT, > - &cursor); > - while (cursor.remaining) { > - if (place->fpfn < PFN_DOWN(cursor.start + cursor.size) > - && !(place->lpfn && > - place->lpfn <= PFN_DOWN(cursor.start))) > - return true; > - > - amdgpu_res_next(&cursor, cursor.size); > - } > + if (bo->resource->mem_type == TTM_PL_TT && > + amdgpu_bo_encrypted(ttm_to_amdgpu_bo(bo))) > return false; > > - default: > - break; > - } > - > return ttm_bo_eviction_valuable(bo, place); > } > > diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c > index c1bd006a5525..03409409e43e 100644 > --- a/drivers/gpu/drm/ttm/ttm_bo.c > +++ b/drivers/gpu/drm/ttm/ttm_bo.c > @@ -518,6 +518,9 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, > bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, > const struct ttm_place *place) > { > + struct ttm_resource *res = bo->resource; > + struct ttm_device *bdev = bo->bdev; > + > dma_resv_assert_held(bo->base.resv); > if (bo->resource->mem_type == TTM_PL_SYSTEM) > return true; > @@ -525,11 +528,7 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, > /* Don't evict this BO if it's outside of the > * requested placement range > */ > - if (place->fpfn >= (bo->resource->start + bo->resource->num_pages) || > - (place->lpfn && place->lpfn <= bo->resource->start)) > - return false; > - > - return true; > + return ttm_resource_intersect(bdev, res, place, bo->base.size); > } > EXPORT_SYMBOL(ttm_bo_eviction_valuable); > > diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c > index 84c21f92b422..ff3e9058943c 100644 > --- a/drivers/gpu/drm/ttm/ttm_resource.c > +++ b/drivers/gpu/drm/ttm/ttm_resource.c > @@ -285,6 +285,8 @@ static bool ttm_resource_places_compat(struct ttm_resource *res, > const struct ttm_place *places, > unsigned num_placement) > { > + struct ttm_buffer_object *bo = res->bo; > + struct ttm_device *bdev = bo->bdev; > unsigned i; > > if (res->placement & TTM_PL_FLAG_TEMPORARY) > @@ -293,8 +295,7 @@ static bool ttm_resource_places_compat(struct ttm_resource *res, > for (i = 0; i < num_placement; i++) { > const struct ttm_place *heap = &places[i]; > > - if (res->start < heap->fpfn || (heap->lpfn && > - (res->start + res->num_pages) > heap->lpfn)) > + if (!ttm_resource_intersect(bdev, res, heap, bo->base.size))Thinking more about it that probably won't work like this. Intersection doesn't mean the placement is compatible (e.g. it can be that we only partial intersect). We need to add a separate callback for that I think. Regards, Christian.> continue; > > if ((res->mem_type == heap->mem_type) &&