drm/i915/ttm: wire up the object offset
authorMatthew Auld <matthew.auld@intel.com>
Tue, 15 Mar 2022 18:14:23 +0000 (18:14 +0000)
committerMatthew Auld <matthew.auld@intel.com>
Wed, 16 Mar 2022 17:50:38 +0000 (17:50 +0000)
For the ttm backend we can use existing placements fpfn and lpfn to
force the allocator to place the object at the requested offset,
potentially evicting stuff if the spot is currently occupied.

Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220315181425.576828-5-matthew.auld@intel.com
drivers/gpu/drm/i915/gem/i915_gem_object_types.h
drivers/gpu/drm/i915/gem/i915_gem_ttm.c
drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
drivers/gpu/drm/i915/intel_region_ttm.c
drivers/gpu/drm/i915/intel_region_ttm.h
drivers/gpu/drm/i915/selftests/mock_region.c

index fd54eb8f48264209e5df516e35f4805a000ceb78..2c88bdb8ff7cc89fd802a85d305827e8bfc0fca8 100644 (file)
@@ -631,6 +631,8 @@ struct drm_i915_gem_object {
 
                struct drm_mm_node *stolen;
 
+               resource_size_t bo_offset;
+
                unsigned long scratch;
                u64 encode;
 
index 5e543ed867a203ed210b50356e8ba5951b646f43..e4a06fcf741ad074ea4927c454db33370f1a31fd 100644 (file)
@@ -126,6 +126,8 @@ i915_ttm_select_tt_caching(const struct drm_i915_gem_object *obj)
 static void
 i915_ttm_place_from_region(const struct intel_memory_region *mr,
                           struct ttm_place *place,
+                          resource_size_t offset,
+                          resource_size_t size,
                           unsigned int flags)
 {
        memset(place, 0, sizeof(*place));
@@ -133,7 +135,10 @@ i915_ttm_place_from_region(const struct intel_memory_region *mr,
 
        if (flags & I915_BO_ALLOC_CONTIGUOUS)
                place->flags |= TTM_PL_FLAG_CONTIGUOUS;
-       if (mr->io_size && mr->io_size < mr->total) {
+       if (offset != I915_BO_INVALID_OFFSET) {
+               place->fpfn = offset >> PAGE_SHIFT;
+               place->lpfn = place->fpfn + (size >> PAGE_SHIFT);
+       } else if (mr->io_size && mr->io_size < mr->total) {
                if (flags & I915_BO_ALLOC_GPU_ONLY) {
                        place->flags |= TTM_PL_FLAG_TOPDOWN;
                } else {
@@ -155,12 +160,14 @@ i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj,
 
        placement->num_placement = 1;
        i915_ttm_place_from_region(num_allowed ? obj->mm.placements[0] :
-                                  obj->mm.region, requested, flags);
+                                  obj->mm.region, requested, obj->bo_offset,
+                                  obj->base.size, flags);
 
        /* 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, flags);
+               i915_ttm_place_from_region(obj->mm.placements[i], busy + i,
+                                          obj->bo_offset, obj->base.size, flags);
 
        if (num_allowed == 0) {
                *busy = *requested;
@@ -802,7 +809,8 @@ static int __i915_ttm_migrate(struct drm_i915_gem_object *obj,
        struct ttm_placement placement;
        int ret;
 
-       i915_ttm_place_from_region(mr, &requested, flags);
+       i915_ttm_place_from_region(mr, &requested, obj->bo_offset,
+                                  obj->base.size, flags);
        placement.num_placement = 1;
        placement.num_busy_placement = 1;
        placement.placement = &requested;
@@ -1159,6 +1167,8 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
        drm_gem_private_object_init(&i915->drm, &obj->base, size);
        i915_gem_object_init(obj, &i915_gem_ttm_obj_ops, &lock_class, flags);
 
+       obj->bo_offset = offset;
+
        /* Don't put on a region list until we're either locked or fully initialized. */
        obj->mm.region = mem;
        INIT_LIST_HEAD(&obj->mm.region_link);
index 129f668f21ff46b673a5d6c7f7587c954c3b217b..8e4e3f72c1ef9fd7fd16974a342c0efec753b6fa 100644 (file)
@@ -71,7 +71,8 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
 
        GEM_BUG_ON(min_page_size < mm->chunk_size);
 
-       if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
+       if (place->fpfn + bman_res->base.num_pages != place->lpfn &&
+           place->flags & TTM_PL_FLAG_CONTIGUOUS) {
                unsigned long pages;
 
                size = roundup_pow_of_two(size);
index 737ef3f4ab54e6d251e13f9023c34b70d47a105d..62ff77445b01bafff4be69e17bc5c0a1d5f71e8b 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "intel_region_ttm.h"
 
+#include "gem/i915_gem_region.h"
 #include "gem/i915_gem_ttm.h" /* For the funcs/ops export only */
 /**
  * DOC: TTM support structure
@@ -191,6 +192,7 @@ intel_region_ttm_resource_to_rsgt(struct intel_memory_region *mem,
  */
 struct ttm_resource *
 intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
+                               resource_size_t offset,
                                resource_size_t size,
                                unsigned int flags)
 {
@@ -202,7 +204,10 @@ intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
 
        if (flags & I915_BO_ALLOC_CONTIGUOUS)
                place.flags |= TTM_PL_FLAG_CONTIGUOUS;
-       if (mem->io_size && mem->io_size < mem->total) {
+       if (offset != I915_BO_INVALID_OFFSET) {
+               place.fpfn = offset >> PAGE_SHIFT;
+               place.lpfn = place.fpfn + (size >> PAGE_SHIFT);
+       } else if (mem->io_size && mem->io_size < mem->total) {
                if (flags & I915_BO_ALLOC_GPU_ONLY) {
                        place.flags |= TTM_PL_FLAG_TOPDOWN;
                } else {
index fdee5e7bd46caa30c2d8ee3f8048bbd6f38c06fd..cf9d86dcf409c7f9e55819fda62922bbe05a05ed 100644 (file)
@@ -36,6 +36,7 @@ struct ttm_device_funcs *i915_ttm_driver(void);
 #ifdef CONFIG_DRM_I915_SELFTEST
 struct ttm_resource *
 intel_region_ttm_resource_alloc(struct intel_memory_region *mem,
+                               resource_size_t offset,
                                resource_size_t size,
                                unsigned int flags);
 #endif
index f16c0b7198c73e00d562f8a904a15d32e44feffb..670557ce1024aa6203a0a864ca247f354bb1ed57 100644 (file)
@@ -26,6 +26,7 @@ static int mock_region_get_pages(struct drm_i915_gem_object *obj)
        int err;
 
        obj->mm.res = intel_region_ttm_resource_alloc(obj->mm.region,
+                                                     obj->bo_offset,
                                                      obj->base.size,
                                                      obj->flags);
        if (IS_ERR(obj->mm.res))
@@ -71,6 +72,8 @@ static int mock_object_init(struct intel_memory_region *mem,
        drm_gem_private_object_init(&i915->drm, &obj->base, size);
        i915_gem_object_init(obj, &mock_region_obj_ops, &lock_class, flags);
 
+       obj->bo_offset = offset;
+
        obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT;
 
        i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);