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:
parent
3aae9d0853
commit
da1184cd41
|
@ -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,
|
||||
|
|
|
@ -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,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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue