Commit da1184cd authored by Matthew Auld's avatar Matthew Auld Committed by Chris Wilson
Browse files

drm/i915: treat shmem as a region



Convert shmem to an intel_memory_region.

Signed-off-by: default avatarMatthew Auld <matthew.auld@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Abdiel Janulgue <abdiel.janulgue@linux.intel.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20191018090751.28295-2-matthew.auld@intel.com
parent 3aae9d08
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -25,10 +25,11 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj);
void i915_gem_object_init(struct drm_i915_gem_object *obj,
			  const struct drm_i915_gem_object_ops *ops);
struct drm_i915_gem_object *
i915_gem_object_create_shmem(struct drm_i915_private *i915, u64 size);
i915_gem_object_create_shmem(struct drm_i915_private *i915,
			     resource_size_t size);
struct drm_i915_gem_object *
i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915,
				       const void *data, size_t size);
				       const void *data, resource_size_t size);

extern const struct drm_i915_gem_object_ops i915_gem_shmem_ops;
void __i915_gem_object_release_shmem(struct drm_i915_gem_object *obj,
+4 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include "gt/intel_gt.h"
#include "i915_drv.h"
#include "i915_gem_object.h"
#include "i915_gem_region.h"
#include "i915_scatterlist.h"

static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
@@ -191,8 +192,10 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align)
	/* Perma-pin (until release) the physical set of pages */
	__i915_gem_object_pin_pages(obj);

	if (!IS_ERR_OR_NULL(pages))
	if (!IS_ERR_OR_NULL(pages)) {
		i915_gem_shmem_ops.put_pages(obj, pages);
		i915_gem_object_release_memory_region(obj);
	}
	mutex_unlock(&obj->mm.lock);
	return 0;

+6 −1
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#include "intel_memory_region.h"
#include "i915_gem_region.h"
#include "i915_drv.h"
#include "i915_trace.h"

void
i915_gem_object_put_pages_buddy(struct drm_i915_gem_object *obj,
@@ -165,5 +166,9 @@ i915_gem_object_create_region(struct intel_memory_region *mem,
	if (overflows_type(size, obj->base.size))
		return ERR_PTR(-E2BIG);

	return mem->ops->create_object(mem, size, flags);
	obj = mem->ops->create_object(mem, size, flags);
	if (!IS_ERR(obj))
		trace_i915_gem_object_create(obj);

	return obj;
}
+58 −21
Original line number Diff line number Diff line
@@ -7,7 +7,9 @@
#include <linux/pagevec.h>
#include <linux/swap.h>

#include "gem/i915_gem_region.h"
#include "i915_drv.h"
#include "i915_gemfs.h"
#include "i915_gem_object.h"
#include "i915_scatterlist.h"
#include "i915_trace.h"
@@ -26,6 +28,7 @@ static void check_release_pagevec(struct pagevec *pvec)
static int shmem_get_pages(struct drm_i915_gem_object *obj)
{
	struct drm_i915_private *i915 = to_i915(obj->base.dev);
	struct intel_memory_region *mem = obj->mm.region;
	const unsigned long page_count = obj->base.size / PAGE_SIZE;
	unsigned long i;
	struct address_space *mapping;
@@ -52,7 +55,7 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj)
	 * If there's no chance of allocating enough pages for the whole
	 * object, bail early.
	 */
	if (page_count > totalram_pages())
	if (obj->base.size > resource_size(&mem->region))
		return -ENOMEM;

	st = kmalloc(sizeof(*st), GFP_KERNEL);
@@ -417,6 +420,8 @@ shmem_pwrite(struct drm_i915_gem_object *obj,

static void shmem_release(struct drm_i915_gem_object *obj)
{
	i915_gem_object_release_memory_region(obj);

	fput(obj->base.filp);
}

@@ -434,9 +439,9 @@ const struct drm_i915_gem_object_ops i915_gem_shmem_ops = {
	.release = shmem_release,
};

static int create_shmem(struct drm_i915_private *i915,
static int __create_shmem(struct drm_i915_private *i915,
			  struct drm_gem_object *obj,
			size_t size)
			  resource_size_t size)
{
	unsigned long flags = VM_NORESERVE;
	struct file *filp;
@@ -455,31 +460,23 @@ static int create_shmem(struct drm_i915_private *i915,
	return 0;
}

struct drm_i915_gem_object *
i915_gem_object_create_shmem(struct drm_i915_private *i915, u64 size)
static struct drm_i915_gem_object *
create_shmem(struct intel_memory_region *mem,
	     resource_size_t size,
	     unsigned int flags)
{
	struct drm_i915_private *i915 = mem->i915;
	struct drm_i915_gem_object *obj;
	struct address_space *mapping;
	unsigned int cache_level;
	gfp_t mask;
	int ret;

	/* There is a prevalence of the assumption that we fit the object's
	 * page count inside a 32bit _signed_ variable. Let's document this and
	 * catch if we ever need to fix it. In the meantime, if you do spot
	 * such a local variable, please consider fixing!
	 */
	if (size >> PAGE_SHIFT > INT_MAX)
		return ERR_PTR(-E2BIG);

	if (overflows_type(size, obj->base.size))
		return ERR_PTR(-E2BIG);

	obj = i915_gem_object_alloc();
	if (!obj)
		return ERR_PTR(-ENOMEM);

	ret = create_shmem(i915, &obj->base, size);
	ret = __create_shmem(i915, &obj->base, size);
	if (ret)
		goto fail;

@@ -518,7 +515,7 @@ i915_gem_object_create_shmem(struct drm_i915_private *i915, u64 size)

	i915_gem_object_set_cache_coherency(obj, cache_level);

	trace_i915_gem_object_create(obj);
	i915_gem_object_init_memory_region(obj, mem, 0);

	return obj;

@@ -527,14 +524,22 @@ fail:
	return ERR_PTR(ret);
}

struct drm_i915_gem_object *
i915_gem_object_create_shmem(struct drm_i915_private *i915,
			     resource_size_t size)
{
	return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_SMEM],
					     size, 0);
}

/* Allocate a new GEM object and fill it with the supplied data */
struct drm_i915_gem_object *
i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv,
				       const void *data, size_t size)
				       const void *data, resource_size_t size)
{
	struct drm_i915_gem_object *obj;
	struct file *file;
	size_t offset;
	resource_size_t offset;
	int err;

	obj = i915_gem_object_create_shmem(dev_priv, round_up(size, PAGE_SIZE));
@@ -577,3 +582,35 @@ fail:
	i915_gem_object_put(obj);
	return ERR_PTR(err);
}

static int init_shmem(struct intel_memory_region *mem)
{
	int err;

	err = i915_gemfs_init(mem->i915);
	if (err) {
		DRM_NOTE("Unable to create a private tmpfs mount, hugepage support will be disabled(%d).\n",
			 err);
	}

	return 0; /* Don't error, we can simply fallback to the kernel mnt */
}

static void release_shmem(struct intel_memory_region *mem)
{
	i915_gemfs_fini(mem->i915);
}

static const struct intel_memory_region_ops shmem_region_ops = {
	.init = init_shmem,
	.release = release_shmem,
	.create_object = create_shmem,
};

struct intel_memory_region *i915_gem_shmem_setup(struct drm_i915_private *i915)
{
	return intel_memory_region_create(i915, 0,
					  totalram_pages() << PAGE_SHIFT,
					  PAGE_SIZE, 0,
					  &shmem_region_ops);
}
+2 −0
Original line number Diff line number Diff line
@@ -1876,6 +1876,8 @@ void i915_gem_cleanup_early(struct drm_i915_private *dev_priv);
int i915_gem_freeze(struct drm_i915_private *dev_priv);
int i915_gem_freeze_late(struct drm_i915_private *dev_priv);

struct intel_memory_region *i915_gem_shmem_setup(struct drm_i915_private *i915);

static inline void i915_gem_drain_freed_objects(struct drm_i915_private *i915)
{
	/*
Loading