Signed-off-by: Robert Beckett <bob.beck...@collabora.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_region.c | 55 ++++++++++++++
 drivers/gpu/drm/i915/gem/i915_gem_region.h |  6 ++
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c    | 84 ++++++++++++++++++----
 drivers/gpu/drm/i915/intel_memory_region.h |  6 ++
 4 files changed, 136 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c 
b/drivers/gpu/drm/i915/gem/i915_gem_region.c
index c9b2e8b91053..e25ad0b9b636 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_region.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c
@@ -98,6 +98,61 @@ i915_gem_object_create_region(struct intel_memory_region 
*mem,
        return ERR_PTR(err);
 }
 
+struct drm_i915_gem_object *
+i915_gem_object_create_region_in_place(struct intel_memory_region *mem,
+                                      resource_size_t size,
+                                      resource_size_t page_size,
+                                      unsigned int flags,
+                                      u64 start, u64 end)
+{
+       struct drm_i915_gem_object *obj;
+       resource_size_t default_page_size;
+       int err;
+
+       /*
+        * NB: Our use of resource_size_t for the size stems from using struct
+        * resource for the mem->region. We might need to revisit this in the
+        * future.
+        */
+
+       GEM_BUG_ON(flags & ~I915_BO_ALLOC_FLAGS);
+
+       if (!mem)
+               return ERR_PTR(-ENODEV);
+       if (!mem->ops->init_object_in_place)
+               return ERR_PTR(-EINVAL);
+
+       default_page_size = mem->min_page_size;
+       if (page_size)
+               default_page_size = page_size;
+
+       GEM_BUG_ON(!is_power_of_2_u64(default_page_size));
+       GEM_BUG_ON(default_page_size < PAGE_SIZE);
+
+       size = round_up(size, default_page_size);
+
+       GEM_BUG_ON(!size);
+       GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_MIN_ALIGNMENT));
+
+       if (i915_gem_object_size_2big(size))
+               return ERR_PTR(-E2BIG);
+
+       obj = i915_gem_object_alloc();
+       if (!obj)
+               return ERR_PTR(-ENOMEM);
+
+       err = mem->ops->init_object_in_place(mem, obj, size, page_size, flags, 
start, end);
+       if (err)
+               goto err_object_free;
+
+       trace_i915_gem_object_create(obj);
+       return obj;
+
+err_object_free:
+       i915_gem_object_free(obj);
+       return ERR_PTR(err);
+}
+
 /**
  * i915_gem_process_region - Iterate over all objects of a region using ops
  * to process and optionally skip objects
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.h 
b/drivers/gpu/drm/i915/gem/i915_gem_region.h
index fcaa12d657d4..0cad90ac4a92 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_region.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_region.h
@@ -56,6 +56,12 @@ i915_gem_object_create_region(struct intel_memory_region 
*mem,
                              resource_size_t size,
                              resource_size_t page_size,
                              unsigned int flags);
+struct drm_i915_gem_object *
+i915_gem_object_create_region_in_place(struct intel_memory_region *mem,
+                                      resource_size_t size,
+                                      resource_size_t page_size,
+                                      unsigned int flags,
+                                      u64 start, u64 end);
 
 int i915_gem_process_region(struct intel_memory_region *mr,
                            struct i915_gem_apply_to_region *apply);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c 
b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 45cc5837ce00..35d1bde19267 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -1131,20 +1131,12 @@ void i915_ttm_bo_destroy(struct ttm_buffer_object *bo)
        }
 }
 
-/**
- * __i915_gem_ttm_object_init - Initialize a ttm-backed i915 gem object
- * @mem: The initial memory region for the object.
- * @obj: The gem object.
- * @size: Object size in bytes.
- * @flags: gem object flags.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
-                              struct drm_i915_gem_object *obj,
-                              resource_size_t size,
-                              resource_size_t page_size,
-                              unsigned int flags)
+static int __i915_gem_ttm_object_init_with_placement(struct 
intel_memory_region *mem,
+                                                    struct drm_i915_gem_object 
*obj,
+                                                    resource_size_t size,
+                                                    resource_size_t page_size,
+                                                    unsigned int flags,
+                                                    struct ttm_placement 
*placement)
 {
        static struct lock_class_key lock_class;
        struct drm_i915_private *i915 = mem->i915;
@@ -1188,7 +1180,7 @@ int __i915_gem_ttm_object_init(struct intel_memory_region 
*mem,
         * until successful initialization.
         */
        ret = ttm_bo_init_reserved(&i915->bdev, i915_gem_to_ttm(obj), size,
-                                  bo_type, &i915_sys_placement,
+                                  bo_type, placement,
                                   page_size >> PAGE_SHIFT,
                                   &ctx, NULL, NULL, i915_ttm_bo_destroy);
        if (ret)
@@ -1204,8 +1196,70 @@ int __i915_gem_ttm_object_init(struct 
intel_memory_region *mem,
        return 0;
 }
 
+/**
+ * __i915_gem_ttm_object_init - Initialize a ttm-backed i915 gem object
+ * @mem: The initial memory region for the object.
+ * @obj: The gem object.
+ * @size: Object size in bytes.
+ * @flags: gem object flags.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
+                              struct drm_i915_gem_object *obj,
+                              resource_size_t size,
+                              resource_size_t page_size,
+                              unsigned int flags)
+{
+       return __i915_gem_ttm_object_init_with_placement(mem, obj, size,
+                                                        page_size, flags,
+                                                        &i915_sys_placement);
+}
+
+/**
+ * i915_gem_ttm_object_init_in_place - Initialize a ttm-backed i915 gem object 
in place
+ * @mem: The initial memory region for the object.
+ * @obj: The gem object.
+ * @size: Object size in bytes.
+ * @page_size: Required page size.
+ * @flags: gem object flags.
+ * @start: start of range to insert in to.
+ * @end: end of range to insert in to.
+ *
+ * Initializes a ttm-backed i915 gem object with a predefined
+ * placement and range.
+ * Can be used to create an object around a pre-reserved area.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int i915_gem_ttm_object_init_in_place(struct intel_memory_region *mem,
+                                            struct drm_i915_gem_object *obj,
+                                            resource_size_t size,
+                                            resource_size_t page_size,
+                                            unsigned int flags,
+                                            u64 start,
+                                            u64 end)
+{
+       struct ttm_place place;
+       struct ttm_placement placement = {
+               .num_placement = 1,
+               .placement = &place,
+               .num_busy_placement = 1,
+               .busy_placement = &place,
+       };
+
+       i915_ttm_place_from_region(mem, &place, flags);
+       place.fpfn = PFN_DOWN(start);
+       place.lpfn = PFN_UP(end);
+
+       return __i915_gem_ttm_object_init_with_placement(mem, obj, size,
+                                                        page_size, flags,
+                                                        &placement);
+}
+
 static const struct intel_memory_region_ops ttm_system_region_ops = {
        .init_object = __i915_gem_ttm_object_init,
+       .init_object_in_place = i915_gem_ttm_object_init_in_place,
        .release = intel_region_ttm_fini,
 };
 
diff --git a/drivers/gpu/drm/i915/intel_memory_region.h 
b/drivers/gpu/drm/i915/intel_memory_region.h
index 21dcbd620758..eb72997df8f7 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.h
+++ b/drivers/gpu/drm/i915/intel_memory_region.h
@@ -57,6 +57,12 @@ struct intel_memory_region_ops {
                           resource_size_t size,
                           resource_size_t page_size,
                           unsigned int flags);
+       int (*init_object_in_place)(struct intel_memory_region *mem,
+                                   struct drm_i915_gem_object *obj,
+                                   resource_size_t size,
+                                   resource_size_t page_size,
+                                   unsigned int flags,
+                                   u64 start, u64 end);
 };
 
 struct intel_memory_region {
-- 
2.25.1

Reply via email to