提交 d57d4a1d 编写于 作者: C CQ Tang 提交者: Matthew Auld

drm/i915: Create stolen memory region from local memory

Add "REGION_STOLEN" device info to dg1, create stolen memory
region from upper portion of local device memory, starting
from DSMBASE.

v2:
    - s/drm_info/drm_dbg; userspace likely doesn't care about stolen.
    - mem->type is only setup after the region probe, so setting the name
      as stolen-local or stolen-system based on this value won't work. Split
      system vs local stolen setup to fix this.
    - kill all the region->devmem/is_devmem stuff. We already differentiate
      the different types of stolen so such things shouldn't be needed
      anymore.
v3:
    - split stolen lmem vs smem ops(Tvrtko)
    - add shortcut for stolen region in i915(Tvrtko)
    - sanity check dsm base vs bar size(Xinyun)
v4(Tvrtko):
    - more cleanup
    - add some TODOs
Signed-off-by: NCQ Tang <cq.tang@intel.com>
Signed-off-by: NMatthew Auld <matthew.auld@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Cc: Xinyun Liu <xinyun.liu@intel.com>
Reviewed-by: NTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210421104658.304142-1-matthew.auld@intel.com
上级 c256af0d
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <drm/drm_mm.h> #include <drm/drm_mm.h>
#include <drm/i915_drm.h> #include <drm/i915_drm.h>
#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h" #include "gem/i915_gem_region.h"
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_gem_stolen.h" #include "i915_gem_stolen.h"
...@@ -121,6 +122,14 @@ static int i915_adjust_stolen(struct drm_i915_private *i915, ...@@ -121,6 +122,14 @@ static int i915_adjust_stolen(struct drm_i915_private *i915,
} }
} }
/*
* With stolen lmem, we don't need to check if the address range
* overlaps with the non-stolen system memory range, since lmem is local
* to the gpu.
*/
if (HAS_LMEM(i915))
return 0;
/* /*
* Verify that nothing else uses this physical address. Stolen * Verify that nothing else uses this physical address. Stolen
* memory should be reserved by the BIOS and hidden from the * memory should be reserved by the BIOS and hidden from the
...@@ -374,8 +383,9 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915, ...@@ -374,8 +383,9 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915,
} }
} }
static int i915_gem_init_stolen(struct drm_i915_private *i915) static int i915_gem_init_stolen(struct intel_memory_region *mem)
{ {
struct drm_i915_private *i915 = mem->i915;
struct intel_uncore *uncore = &i915->uncore; struct intel_uncore *uncore = &i915->uncore;
resource_size_t reserved_base, stolen_top; resource_size_t reserved_base, stolen_top;
resource_size_t reserved_total, reserved_size; resource_size_t reserved_total, reserved_size;
...@@ -396,10 +406,10 @@ static int i915_gem_init_stolen(struct drm_i915_private *i915) ...@@ -396,10 +406,10 @@ static int i915_gem_init_stolen(struct drm_i915_private *i915)
return 0; return 0;
} }
if (resource_size(&intel_graphics_stolen_res) == 0) if (resource_size(&mem->region) == 0)
return 0; return 0;
i915->dsm = intel_graphics_stolen_res; i915->dsm = mem->region;
if (i915_adjust_stolen(i915, &i915->dsm)) if (i915_adjust_stolen(i915, &i915->dsm))
return 0; return 0;
...@@ -688,39 +698,123 @@ struct drm_i915_gem_object * ...@@ -688,39 +698,123 @@ struct drm_i915_gem_object *
i915_gem_object_create_stolen(struct drm_i915_private *i915, i915_gem_object_create_stolen(struct drm_i915_private *i915,
resource_size_t size) resource_size_t size)
{ {
return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_STOLEN_SMEM], return i915_gem_object_create_region(i915->mm.stolen_region,
size, I915_BO_ALLOC_CONTIGUOUS); size, I915_BO_ALLOC_CONTIGUOUS);
} }
static int init_stolen(struct intel_memory_region *mem) static int init_stolen_smem(struct intel_memory_region *mem)
{ {
intel_memory_region_set_name(mem, "stolen");
/* /*
* Initialise stolen early so that we may reserve preallocated * Initialise stolen early so that we may reserve preallocated
* objects for the BIOS to KMS transition. * objects for the BIOS to KMS transition.
*/ */
return i915_gem_init_stolen(mem->i915); return i915_gem_init_stolen(mem);
} }
static void release_stolen(struct intel_memory_region *mem) static void release_stolen_smem(struct intel_memory_region *mem)
{ {
i915_gem_cleanup_stolen(mem->i915); i915_gem_cleanup_stolen(mem->i915);
} }
static const struct intel_memory_region_ops i915_region_stolen_ops = { static const struct intel_memory_region_ops i915_region_stolen_smem_ops = {
.init = init_stolen, .init = init_stolen_smem,
.release = release_stolen, .release = release_stolen_smem,
.init_object = _i915_gem_object_stolen_init, .init_object = _i915_gem_object_stolen_init,
}; };
struct intel_memory_region *i915_gem_stolen_setup(struct drm_i915_private *i915) static int init_stolen_lmem(struct intel_memory_region *mem)
{
int err;
if (GEM_WARN_ON(resource_size(&mem->region) == 0))
return -ENODEV;
if (!io_mapping_init_wc(&mem->iomap,
mem->io_start,
resource_size(&mem->region)))
return -EIO;
/*
* TODO: For stolen lmem we mostly just care about populating the dsm
* related bits and setting up the drm_mm allocator for the range.
* Perhaps split up i915_gem_init_stolen() for this.
*/
err = i915_gem_init_stolen(mem);
if (err)
goto err_fini;
return 0;
err_fini:
io_mapping_fini(&mem->iomap);
return err;
}
static void release_stolen_lmem(struct intel_memory_region *mem)
{ {
return intel_memory_region_create(i915, io_mapping_fini(&mem->iomap);
intel_graphics_stolen_res.start, i915_gem_cleanup_stolen(mem->i915);
resource_size(&intel_graphics_stolen_res), }
PAGE_SIZE, 0,
&i915_region_stolen_ops); static const struct intel_memory_region_ops i915_region_stolen_lmem_ops = {
.init = init_stolen_lmem,
.release = release_stolen_lmem,
.init_object = _i915_gem_object_stolen_init,
};
struct intel_memory_region *
i915_gem_stolen_lmem_setup(struct drm_i915_private *i915)
{
struct intel_uncore *uncore = &i915->uncore;
struct pci_dev *pdev = i915->drm.pdev;
struct intel_memory_region *mem;
resource_size_t io_start;
resource_size_t lmem_size;
u64 lmem_base;
lmem_base = intel_uncore_read64(uncore, GEN12_DSMBASE);
if (GEM_WARN_ON(lmem_base >= pci_resource_len(pdev, 2)))
return ERR_PTR(-ENODEV);
lmem_size = pci_resource_len(pdev, 2) - lmem_base;
io_start = pci_resource_start(pdev, 2) + lmem_base;
mem = intel_memory_region_create(i915, lmem_base, lmem_size,
I915_GTT_PAGE_SIZE_4K, io_start,
&i915_region_stolen_lmem_ops);
if (IS_ERR(mem))
return mem;
/*
* TODO: consider creating common helper to just print all the
* interesting stuff from intel_memory_region, which we can use for all
* our probed regions.
*/
drm_dbg(&i915->drm, "Stolen Local memory IO start: %pa\n",
&mem->io_start);
intel_memory_region_set_name(mem, "stolen-local");
return mem;
}
struct intel_memory_region*
i915_gem_stolen_smem_setup(struct drm_i915_private *i915)
{
struct intel_memory_region *mem;
mem = intel_memory_region_create(i915,
intel_graphics_stolen_res.start,
resource_size(&intel_graphics_stolen_res),
PAGE_SIZE, 0,
&i915_region_stolen_smem_ops);
if (IS_ERR(mem))
return mem;
intel_memory_region_set_name(mem, "stolen-system");
return mem;
} }
struct drm_i915_gem_object * struct drm_i915_gem_object *
...@@ -728,7 +822,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915, ...@@ -728,7 +822,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915,
resource_size_t stolen_offset, resource_size_t stolen_offset,
resource_size_t size) resource_size_t size)
{ {
struct intel_memory_region *mem = i915->mm.regions[INTEL_REGION_STOLEN_SMEM]; struct intel_memory_region *mem = i915->mm.stolen_region;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
struct drm_mm_node *stolen; struct drm_mm_node *stolen;
int ret; int ret;
......
...@@ -21,7 +21,8 @@ int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv, ...@@ -21,7 +21,8 @@ int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv,
u64 end); u64 end);
void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
struct drm_mm_node *node); struct drm_mm_node *node);
struct intel_memory_region *i915_gem_stolen_setup(struct drm_i915_private *i915); struct intel_memory_region *i915_gem_stolen_smem_setup(struct drm_i915_private *i915);
struct intel_memory_region *i915_gem_stolen_lmem_setup(struct drm_i915_private *i915);
struct drm_i915_gem_object * struct drm_i915_gem_object *
i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, i915_gem_object_create_stolen(struct drm_i915_private *dev_priv,
resource_size_t size); resource_size_t size);
......
...@@ -514,6 +514,13 @@ struct intel_l3_parity { ...@@ -514,6 +514,13 @@ struct intel_l3_parity {
}; };
struct i915_gem_mm { struct i915_gem_mm {
/*
* Shortcut for the stolen region. This points to either
* INTEL_REGION_STOLEN_SMEM for integrated platforms, or
* INTEL_REGION_STOLEN_LMEM for discrete, or NULL if the device doesn't
* support stolen.
*/
struct intel_memory_region *stolen_region;
/** Memory allocator for GTT stolen memory */ /** Memory allocator for GTT stolen memory */
struct drm_mm stolen; struct drm_mm stolen;
/** Protects the usage of the GTT stolen memory allocator. This is /** Protects the usage of the GTT stolen memory allocator. This is
......
...@@ -908,7 +908,7 @@ static const struct intel_device_info rkl_info = { ...@@ -908,7 +908,7 @@ static const struct intel_device_info rkl_info = {
}; };
#define DGFX_FEATURES \ #define DGFX_FEATURES \
.memory_regions = REGION_SMEM | REGION_LMEM, \ .memory_regions = REGION_SMEM | REGION_LMEM | REGION_STOLEN_LMEM, \
.has_master_unit_irq = 1, \ .has_master_unit_irq = 1, \
.has_llc = 0, \ .has_llc = 0, \
.has_snoop = 1, \ .has_snoop = 1, \
......
...@@ -12194,6 +12194,7 @@ enum skl_power_gate { ...@@ -12194,6 +12194,7 @@ enum skl_power_gate {
#define GEN12_GLOBAL_MOCS(i) _MMIO(0x4000 + (i) * 4) /* Global MOCS regs */ #define GEN12_GLOBAL_MOCS(i) _MMIO(0x4000 + (i) * 4) /* Global MOCS regs */
#define GEN12_GSMBASE _MMIO(0x108100) #define GEN12_GSMBASE _MMIO(0x108100)
#define GEN12_DSMBASE _MMIO(0x1080C0)
/* gamt regs */ /* gamt regs */
#define GEN8_L3_LRA_1_GPGPU _MMIO(0x4dd4) #define GEN8_L3_LRA_1_GPGPU _MMIO(0x4dd4)
......
...@@ -22,6 +22,10 @@ static const struct { ...@@ -22,6 +22,10 @@ static const struct {
.class = INTEL_MEMORY_STOLEN_SYSTEM, .class = INTEL_MEMORY_STOLEN_SYSTEM,
.instance = 0, .instance = 0,
}, },
[INTEL_REGION_STOLEN_LMEM] = {
.class = INTEL_MEMORY_STOLEN_LOCAL,
.instance = 0,
},
}; };
struct intel_memory_region * struct intel_memory_region *
...@@ -278,8 +282,15 @@ int intel_memory_regions_hw_probe(struct drm_i915_private *i915) ...@@ -278,8 +282,15 @@ int intel_memory_regions_hw_probe(struct drm_i915_private *i915)
case INTEL_MEMORY_SYSTEM: case INTEL_MEMORY_SYSTEM:
mem = i915_gem_shmem_setup(i915); mem = i915_gem_shmem_setup(i915);
break; break;
case INTEL_MEMORY_STOLEN_LOCAL:
mem = i915_gem_stolen_lmem_setup(i915);
if (!IS_ERR(mem))
i915->mm.stolen_region = mem;
break;
case INTEL_MEMORY_STOLEN_SYSTEM: case INTEL_MEMORY_STOLEN_SYSTEM:
mem = i915_gem_stolen_setup(i915); mem = i915_gem_stolen_smem_setup(i915);
if (!IS_ERR(mem))
i915->mm.stolen_region = mem;
break; break;
default: default:
continue; continue;
......
...@@ -26,18 +26,21 @@ enum intel_memory_type { ...@@ -26,18 +26,21 @@ enum intel_memory_type {
INTEL_MEMORY_SYSTEM = 0, INTEL_MEMORY_SYSTEM = 0,
INTEL_MEMORY_LOCAL, INTEL_MEMORY_LOCAL,
INTEL_MEMORY_STOLEN_SYSTEM, INTEL_MEMORY_STOLEN_SYSTEM,
INTEL_MEMORY_STOLEN_LOCAL,
}; };
enum intel_region_id { enum intel_region_id {
INTEL_REGION_SMEM = 0, INTEL_REGION_SMEM = 0,
INTEL_REGION_LMEM, INTEL_REGION_LMEM,
INTEL_REGION_STOLEN_SMEM, INTEL_REGION_STOLEN_SMEM,
INTEL_REGION_STOLEN_LMEM,
INTEL_REGION_UNKNOWN, /* Should be last */ INTEL_REGION_UNKNOWN, /* Should be last */
}; };
#define REGION_SMEM BIT(INTEL_REGION_SMEM) #define REGION_SMEM BIT(INTEL_REGION_SMEM)
#define REGION_LMEM BIT(INTEL_REGION_LMEM) #define REGION_LMEM BIT(INTEL_REGION_LMEM)
#define REGION_STOLEN_SMEM BIT(INTEL_REGION_STOLEN_SMEM) #define REGION_STOLEN_SMEM BIT(INTEL_REGION_STOLEN_SMEM)
#define REGION_STOLEN_LMEM BIT(INTEL_REGION_STOLEN_LMEM)
#define I915_ALLOC_MIN_PAGE_SIZE BIT(0) #define I915_ALLOC_MIN_PAGE_SIZE BIT(0)
#define I915_ALLOC_CONTIGUOUS BIT(1) #define I915_ALLOC_CONTIGUOUS BIT(1)
...@@ -82,7 +85,7 @@ struct intel_memory_region { ...@@ -82,7 +85,7 @@ struct intel_memory_region {
u16 type; u16 type;
u16 instance; u16 instance;
enum intel_region_id id; enum intel_region_id id;
char name[8]; char name[16];
struct list_head reserved; struct list_head reserved;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册