drm/i915: treat shmem as a region

Convert shmem to an intel_memory_region.

Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Abdiel Janulgue <abdiel.janulgue@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20191018090751.28295-2-matthew.auld@intel.com
This commit is contained in:
Matthew Auld 2019-10-18 10:07:50 +01:00 committed by Chris Wilson
parent 3aae9d0853
commit da1184cd41
11 changed files with 150 additions and 48 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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;
}

View File

@ -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,
struct drm_gem_object *obj,
size_t size)
static int __create_shmem(struct drm_i915_private *i915,
struct drm_gem_object *obj,
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);
}

View File

@ -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)
{
/*

View File

@ -45,7 +45,6 @@
#include "gem/i915_gem_context.h"
#include "gem/i915_gem_ioctls.h"
#include "gem/i915_gem_pm.h"
#include "gem/i915_gemfs.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_gt.h"
#include "gt/intel_gt_pm.h"
@ -1432,16 +1431,10 @@ static void i915_gem_init__mm(struct drm_i915_private *i915)
void i915_gem_init_early(struct drm_i915_private *dev_priv)
{
int err;
i915_gem_init__mm(dev_priv);
i915_gem_init__pm(dev_priv);
spin_lock_init(&dev_priv->fb_tracking.lock);
err = i915_gemfs_init(dev_priv);
if (err)
DRM_NOTE("Unable to create a private tmpfs mount, hugepage support will be disabled(%d).\n", err);
}
void i915_gem_cleanup_early(struct drm_i915_private *dev_priv)
@ -1450,8 +1443,6 @@ void i915_gem_cleanup_early(struct drm_i915_private *dev_priv)
GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list));
GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count));
WARN_ON(dev_priv->mm.shrink_count);
i915_gemfs_fini(dev_priv);
}
int i915_gem_freeze(struct drm_i915_private *dev_priv)

View File

@ -2773,14 +2773,29 @@ int i915_gem_init_memory_regions(struct drm_i915_private *i915)
for (i = 0; i < INTEL_REGION_UNKNOWN; i++) {
struct intel_memory_region *mem = ERR_PTR(-ENODEV);
u32 type;
if (!HAS_REGION(i915, BIT(i)))
continue;
type = MEMORY_TYPE_FROM_REGION(intel_region_map[i]);
switch (type) {
case INTEL_MEMORY_SYSTEM:
mem = i915_gem_shmem_setup(i915);
break;
}
if (IS_ERR(mem)) {
err = PTR_ERR(mem);
DRM_ERROR("Failed to setup region(%d) type=%d\n", err, type);
goto out_cleanup;
}
mem->id = intel_region_map[i];
mem->type = type;
mem->instance = MEMORY_INSTANCE_FROM_REGION(intel_region_map[i]);
i915->mm.regions[i] = mem;
}
return 0;

View File

@ -151,6 +151,9 @@
#define GEN_DEFAULT_PAGE_SIZES \
.page_sizes = I915_GTT_PAGE_SIZE_4K
#define GEN_DEFAULT_REGIONS \
.memory_regions = REGION_SMEM
#define I830_FEATURES \
GEN(2), \
.is_mobile = 1, \
@ -168,7 +171,8 @@
I9XX_PIPE_OFFSETS, \
I9XX_CURSOR_OFFSETS, \
I9XX_COLORS, \
GEN_DEFAULT_PAGE_SIZES
GEN_DEFAULT_PAGE_SIZES, \
GEN_DEFAULT_REGIONS
#define I845_FEATURES \
GEN(2), \
@ -185,7 +189,8 @@
I845_PIPE_OFFSETS, \
I845_CURSOR_OFFSETS, \
I9XX_COLORS, \
GEN_DEFAULT_PAGE_SIZES
GEN_DEFAULT_PAGE_SIZES, \
GEN_DEFAULT_REGIONS
static const struct intel_device_info intel_i830_info = {
I830_FEATURES,
@ -219,7 +224,8 @@ static const struct intel_device_info intel_i865g_info = {
I9XX_PIPE_OFFSETS, \
I9XX_CURSOR_OFFSETS, \
I9XX_COLORS, \
GEN_DEFAULT_PAGE_SIZES
GEN_DEFAULT_PAGE_SIZES, \
GEN_DEFAULT_REGIONS
static const struct intel_device_info intel_i915g_info = {
GEN3_FEATURES,
@ -304,7 +310,8 @@ static const struct intel_device_info intel_pineview_m_info = {
I9XX_PIPE_OFFSETS, \
I9XX_CURSOR_OFFSETS, \
I965_COLORS, \
GEN_DEFAULT_PAGE_SIZES
GEN_DEFAULT_PAGE_SIZES, \
GEN_DEFAULT_REGIONS
static const struct intel_device_info intel_i965g_info = {
GEN4_FEATURES,
@ -354,7 +361,8 @@ static const struct intel_device_info intel_gm45_info = {
I9XX_PIPE_OFFSETS, \
I9XX_CURSOR_OFFSETS, \
ILK_COLORS, \
GEN_DEFAULT_PAGE_SIZES
GEN_DEFAULT_PAGE_SIZES, \
GEN_DEFAULT_REGIONS
static const struct intel_device_info intel_ironlake_d_info = {
GEN5_FEATURES,
@ -384,7 +392,8 @@ static const struct intel_device_info intel_ironlake_m_info = {
I9XX_PIPE_OFFSETS, \
I9XX_CURSOR_OFFSETS, \
ILK_COLORS, \
GEN_DEFAULT_PAGE_SIZES
GEN_DEFAULT_PAGE_SIZES, \
GEN_DEFAULT_REGIONS
#define SNB_D_PLATFORM \
GEN6_FEATURES, \
@ -432,7 +441,8 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info = {
IVB_PIPE_OFFSETS, \
IVB_CURSOR_OFFSETS, \
IVB_COLORS, \
GEN_DEFAULT_PAGE_SIZES
GEN_DEFAULT_PAGE_SIZES, \
GEN_DEFAULT_REGIONS
#define IVB_D_PLATFORM \
GEN7_FEATURES, \
@ -493,6 +503,7 @@ static const struct intel_device_info intel_valleyview_info = {
I9XX_CURSOR_OFFSETS,
I965_COLORS,
GEN_DEFAULT_PAGE_SIZES,
GEN_DEFAULT_REGIONS,
};
#define G75_FEATURES \
@ -587,6 +598,7 @@ static const struct intel_device_info intel_cherryview_info = {
CHV_CURSOR_OFFSETS,
CHV_COLORS,
GEN_DEFAULT_PAGE_SIZES,
GEN_DEFAULT_REGIONS,
};
#define GEN9_DEFAULT_PAGE_SIZES \
@ -661,7 +673,8 @@ static const struct intel_device_info intel_skylake_gt4_info = {
HSW_PIPE_OFFSETS, \
IVB_CURSOR_OFFSETS, \
IVB_COLORS, \
GEN9_DEFAULT_PAGE_SIZES
GEN9_DEFAULT_PAGE_SIZES, \
GEN_DEFAULT_REGIONS
static const struct intel_device_info intel_broxton_info = {
GEN9_LP_FEATURES,

View File

@ -6,6 +6,16 @@
#include "intel_memory_region.h"
#include "i915_drv.h"
/* XXX: Hysterical raisins. BIT(inst) needs to just be (inst) at some point. */
#define REGION_MAP(type, inst) \
BIT((type) + INTEL_MEMORY_TYPE_SHIFT) | BIT(inst)
const u32 intel_region_map[] = {
[INTEL_REGION_SMEM] = REGION_MAP(INTEL_MEMORY_SYSTEM, 0),
[INTEL_REGION_LMEM] = REGION_MAP(INTEL_MEMORY_LOCAL, 0),
[INTEL_REGION_STOLEN] = REGION_MAP(INTEL_MEMORY_STOLEN, 0),
};
static u64
intel_memory_region_free_pages(struct intel_memory_region *mem,
struct list_head *blocks)

View File

@ -18,13 +18,39 @@ struct drm_i915_gem_object;
struct intel_memory_region;
struct sg_table;
enum intel_region_id {
INTEL_REGION_UNKNOWN = 0, /* Should be last */
/**
* Base memory type
*/
enum intel_memory_type {
INTEL_MEMORY_SYSTEM = 0,
INTEL_MEMORY_LOCAL,
INTEL_MEMORY_STOLEN,
};
enum intel_region_id {
INTEL_REGION_SMEM = 0,
INTEL_REGION_LMEM,
INTEL_REGION_STOLEN,
INTEL_REGION_UNKNOWN, /* Should be last */
};
#define REGION_SMEM BIT(INTEL_REGION_SMEM)
#define REGION_LMEM BIT(INTEL_REGION_LMEM)
#define REGION_STOLEN BIT(INTEL_REGION_STOLEN)
#define INTEL_MEMORY_TYPE_SHIFT 16
#define MEMORY_TYPE_FROM_REGION(r) (ilog2((r) >> INTEL_MEMORY_TYPE_SHIFT))
#define MEMORY_INSTANCE_FROM_REGION(r) (ilog2((r) & 0xffff))
#define I915_ALLOC_MIN_PAGE_SIZE BIT(0)
#define I915_ALLOC_CONTIGUOUS BIT(1)
/**
* Memory regions encoded as type | instance
*/
extern const u32 intel_region_map[];
struct intel_memory_region_ops {
unsigned int flags;

View File

@ -72,8 +72,6 @@ static void mock_device_release(struct drm_device *dev)
mock_fini_ggtt(&i915->ggtt);
destroy_workqueue(i915->wq);
i915_gemfs_fini(i915);
i915_gem_cleanup_memory_regions(i915);
drm_mode_config_cleanup(&i915->drm);
@ -165,7 +163,10 @@ struct drm_i915_private *mock_gem_device(void)
I915_GTT_PAGE_SIZE_64K |
I915_GTT_PAGE_SIZE_2M;
mkwrite_device_info(i915)->memory_regions = REGION_SMEM;
mock_uncore_init(&i915->uncore, i915);
i915_gem_init__mm(i915);
intel_gt_init_early(&i915->gt, i915);
atomic_inc(&i915->gt.wakeref.count); /* disable; no hw support */
@ -196,8 +197,6 @@ struct drm_i915_private *mock_gem_device(void)
intel_engines_driver_register(i915);
WARN_ON(i915_gemfs_init(i915));
err = i915_gem_init_memory_regions(i915);
if (err)
goto err_context;