drm/xe/buddy: add compatible and intersects hooks
authorMatthew Auld <matthew.auld@intel.com>
Tue, 21 Mar 2023 11:44:07 +0000 (11:44 +0000)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Tue, 19 Dec 2023 23:30:20 +0000 (18:30 -0500)
Copy this from i915. We need .compatible for vram -> vram transfers, so
they don't just get nooped by ttm, if need to move something from
mappable to non-mappble or vice versa. The .intersects is needed for
eviction, to determine if a victim resource is worth eviction. e.g if we
need mappable space there is no point in evicting a resource that has
zero mappable pages.

Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_ttm_vram_mgr.c

index 78979c0b6024f679c72437a6dccdb6eddc1f5bb3..73836b9b7fed2c6ae7c668e6039627b53f447adc 100644 (file)
@@ -242,9 +242,71 @@ static void xe_ttm_vram_mgr_debug(struct ttm_resource_manager *man,
        drm_printf(printer, "man size:%llu\n", man->size);
 }
 
+static bool xe_ttm_vram_mgr_intersects(struct ttm_resource_manager *man,
+                                      struct ttm_resource *res,
+                                      const struct ttm_place *place,
+                                      size_t size)
+{
+       struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
+       struct xe_ttm_vram_mgr_resource *vres =
+               to_xe_ttm_vram_mgr_resource(res);
+       struct drm_buddy *mm = &mgr->mm;
+       struct drm_buddy_block *block;
+
+       if (!place->fpfn && !place->lpfn)
+               return true;
+
+       if (!place->fpfn && place->lpfn == mgr->visible_size >> PAGE_SHIFT)
+               return vres->used_visible_size > 0;
+
+       list_for_each_entry(block, &vres->blocks, link) {
+               unsigned long fpfn =
+                       drm_buddy_block_offset(block) >> PAGE_SHIFT;
+               unsigned long lpfn = fpfn +
+                       (drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+
+               if (place->fpfn < lpfn && place->lpfn > fpfn)
+                       return true;
+       }
+
+       return false;
+}
+
+static bool xe_ttm_vram_mgr_compatible(struct ttm_resource_manager *man,
+                                      struct ttm_resource *res,
+                                      const struct ttm_place *place,
+                                      size_t size)
+{
+       struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
+       struct xe_ttm_vram_mgr_resource *vres =
+               to_xe_ttm_vram_mgr_resource(res);
+       struct drm_buddy *mm = &mgr->mm;
+       struct drm_buddy_block *block;
+
+       if (!place->fpfn && !place->lpfn)
+               return true;
+
+       if (!place->fpfn && place->lpfn == mgr->visible_size >> PAGE_SHIFT)
+               return vres->used_visible_size == size;
+
+       list_for_each_entry(block, &vres->blocks, link) {
+               unsigned long fpfn =
+                       drm_buddy_block_offset(block) >> PAGE_SHIFT;
+               unsigned long lpfn = fpfn +
+                       (drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+
+               if (fpfn < place->fpfn || lpfn > place->lpfn)
+                       return false;
+       }
+
+       return true;
+}
+
 static const struct ttm_resource_manager_func xe_ttm_vram_mgr_func = {
        .alloc  = xe_ttm_vram_mgr_new,
        .free   = xe_ttm_vram_mgr_del,
+       .intersects = xe_ttm_vram_mgr_intersects,
+       .compatible = xe_ttm_vram_mgr_compatible,
        .debug  = xe_ttm_vram_mgr_debug
 };