drm/i915/ttm: Calculate the object placement at get_pages time
authorThomas Hellström <thomas.hellstrom@linux.intel.com>
Wed, 16 Jun 2021 15:24:57 +0000 (16:24 +0100)
committerMatthew Auld <matthew.auld@intel.com>
Wed, 16 Jun 2021 15:47:54 +0000 (16:47 +0100)
Instead of relying on a static placement, calculate at get_pages() time.
This should work for LMEM regions and system for now. For stolen we need
to take preallocated range into account. That will if needed be added
later.

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210616152501.394518-3-matthew.auld@intel.com
drivers/gpu/drm/i915/gem/i915_gem_ttm.c
drivers/gpu/drm/i915/intel_region_ttm.c
drivers/gpu/drm/i915/intel_region_ttm.h

index cdf36d3..d759568 100644 (file)
 #define I915_TTM_PRIO_NO_PAGES  1
 #define I915_TTM_PRIO_HAS_PAGES 2
 
+/*
+ * Size of struct ttm_place vector in on-stack struct ttm_placement allocs
+ */
+#define I915_TTM_MAX_PLACEMENTS INTEL_REGION_UNKNOWN
+
 /**
  * struct i915_ttm_tt - TTM page vector with additional private information
  * @ttm: The base TTM page vector.
@@ -42,36 +47,71 @@ struct i915_ttm_tt {
        struct sg_table *cached_st;
 };
 
-static const struct ttm_place lmem0_sys_placement_flags[] = {
-       {
-               .fpfn = 0,
-               .lpfn = 0,
-               .mem_type = I915_PL_LMEM0,
-               .flags = 0,
-       }, {
-               .fpfn = 0,
-               .lpfn = 0,
-               .mem_type = I915_PL_SYSTEM,
-               .flags = 0,
-       }
-};
-
-static struct ttm_placement i915_lmem0_placement = {
-       .num_placement = 1,
-       .placement = &lmem0_sys_placement_flags[0],
-       .num_busy_placement = 1,
-       .busy_placement = &lmem0_sys_placement_flags[0],
+static const struct ttm_place sys_placement_flags = {
+       .fpfn = 0,
+       .lpfn = 0,
+       .mem_type = I915_PL_SYSTEM,
+       .flags = 0,
 };
 
 static struct ttm_placement i915_sys_placement = {
        .num_placement = 1,
-       .placement = &lmem0_sys_placement_flags[1],
+       .placement = &sys_placement_flags,
        .num_busy_placement = 1,
-       .busy_placement = &lmem0_sys_placement_flags[1],
+       .busy_placement = &sys_placement_flags,
 };
 
 static void i915_ttm_adjust_lru(struct drm_i915_gem_object *obj);
 
+static enum ttm_caching
+i915_ttm_select_tt_caching(const struct drm_i915_gem_object *obj)
+{
+       /*
+        * Objects only allowed in system get cached cpu-mappings.
+        * Other objects get WC mapping for now. Even if in system.
+        */
+       if (obj->mm.region->type == INTEL_MEMORY_SYSTEM &&
+           obj->mm.n_placements <= 1)
+               return ttm_cached;
+
+       return ttm_write_combined;
+}
+
+static void
+i915_ttm_place_from_region(const struct intel_memory_region *mr,
+                          struct ttm_place *place)
+{
+       memset(place, 0, sizeof(*place));
+       place->mem_type = intel_region_to_ttm_type(mr);
+}
+
+static void
+i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj,
+                           struct ttm_place *requested,
+                           struct ttm_place *busy,
+                           struct ttm_placement *placement)
+{
+       unsigned int num_allowed = obj->mm.n_placements;
+       unsigned int i;
+
+       placement->num_placement = 1;
+       i915_ttm_place_from_region(num_allowed ? obj->mm.placements[0] :
+                                  obj->mm.region, requested);
+
+       /* Cache this on object? */
+       placement->num_busy_placement = num_allowed;
+       for (i = 0; i < placement->num_busy_placement; ++i)
+               i915_ttm_place_from_region(obj->mm.placements[i], busy + i);
+
+       if (num_allowed == 0) {
+               *busy = *requested;
+               placement->num_busy_placement = 1;
+       }
+
+       placement->placement = requested;
+       placement->busy_placement = busy;
+}
+
 static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo,
                                         uint32_t page_flags)
 {
@@ -89,7 +129,8 @@ static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo,
            man->use_tt)
                page_flags |= TTM_PAGE_FLAG_ZERO_ALLOC;
 
-       ret = ttm_tt_init(&i915_tt->ttm, bo, page_flags, ttm_write_combined);
+       ret = ttm_tt_init(&i915_tt->ttm, bo, page_flags,
+                         i915_ttm_select_tt_caching(obj));
        if (ret) {
                kfree(i915_tt);
                return NULL;
@@ -416,10 +457,15 @@ static int i915_ttm_get_pages(struct drm_i915_gem_object *obj)
                .no_wait_gpu = false,
        };
        struct sg_table *st;
+       struct ttm_place requested, busy[I915_TTM_MAX_PLACEMENTS];
+       struct ttm_placement placement;
        int ret;
 
+       GEM_BUG_ON(obj->mm.n_placements > I915_TTM_MAX_PLACEMENTS);
+
        /* Move to the requested placement. */
-       ret = ttm_bo_validate(bo, &i915_lmem0_placement, &ctx);
+       i915_ttm_placement_from_obj(obj, &requested, busy, &placement);
+       ret = ttm_bo_validate(bo, &placement, &ctx);
        if (ret)
                return ret == -ENOSPC ? -ENXIO : ret;
 
@@ -625,7 +671,6 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
        i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
        INIT_RADIX_TREE(&obj->ttm.get_io_page.radix, GFP_KERNEL | __GFP_NOWARN);
        mutex_init(&obj->ttm.get_io_page.lock);
-
        bo_type = (obj->flags & I915_BO_ALLOC_USER) ? ttm_bo_type_device :
                ttm_bo_type_kernel;
 
index 27fe066..5a664f6 100644 (file)
@@ -50,12 +50,16 @@ void intel_region_ttm_device_fini(struct drm_i915_private *dev_priv)
  * driver-private types for now, reserving TTM_PL_VRAM for stolen
  * memory and TTM_PL_TT for GGTT use if decided to implement this.
  */
-static int intel_region_to_ttm_type(struct intel_memory_region *mem)
+int intel_region_to_ttm_type(const struct intel_memory_region *mem)
 {
        int type;
 
        GEM_BUG_ON(mem->type != INTEL_MEMORY_LOCAL &&
-                  mem->type != INTEL_MEMORY_MOCK);
+                  mem->type != INTEL_MEMORY_MOCK &&
+                  mem->type != INTEL_MEMORY_SYSTEM);
+
+       if (mem->type == INTEL_MEMORY_SYSTEM)
+               return TTM_PL_SYSTEM;
 
        type = mem->instance + TTM_PL_PRIV;
        GEM_BUG_ON(type >= TTM_NUM_MEM_TYPES);
index e8cf830..6494918 100644 (file)
@@ -28,6 +28,8 @@ struct sg_table *intel_region_ttm_node_to_st(struct intel_memory_region *mem,
 void intel_region_ttm_node_free(struct intel_memory_region *mem,
                                struct ttm_resource *node);
 
+int intel_region_to_ttm_type(const struct intel_memory_region *mem);
+
 struct ttm_device_funcs *i915_ttm_driver(void);
 
 #ifdef CONFIG_DRM_I915_SELFTEST