Commit d57d4a1d authored by CQ Tang's avatar CQ Tang Committed by Matthew Auld
Browse files

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: default avatarCQ Tang <cq.tang@intel.com>
Signed-off-by: default avatarMatthew Auld <matthew.auld@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Cc: Xinyun Liu <xinyun.liu@intel.com>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210421104658.304142-1-matthew.auld@intel.com
parent c256af0d
Loading
Loading
Loading
Loading
+113 −19
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include <drm/drm_mm.h>
#include <drm/i915_drm.h>

#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h"
#include "i915_drv.h"
#include "i915_gem_stolen.h"
@@ -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
	 * 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,
	}
}

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;
	resource_size_t reserved_base, stolen_top;
	resource_size_t reserved_total, reserved_size;
@@ -396,10 +406,10 @@ static int i915_gem_init_stolen(struct drm_i915_private *i915)
		return 0;
	}

	if (resource_size(&intel_graphics_stolen_res) == 0)
	if (resource_size(&mem->region) == 0)
		return 0;

	i915->dsm = intel_graphics_stolen_res;
	i915->dsm = mem->region;

	if (i915_adjust_stolen(i915, &i915->dsm))
		return 0;
@@ -688,39 +698,123 @@ struct drm_i915_gem_object *
i915_gem_object_create_stolen(struct drm_i915_private *i915,
			      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);
}

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
	 * 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);
}

static const struct intel_memory_region_ops i915_region_stolen_ops = {
	.init = init_stolen,
	.release = release_stolen,
static const struct intel_memory_region_ops i915_region_stolen_smem_ops = {
	.init = init_stolen_smem,
	.release = release_stolen_smem,
	.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);
	i915_gem_cleanup_stolen(mem->i915);
}

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_ops);
					 &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 *
@@ -728,7 +822,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915,
					       resource_size_t stolen_offset,
					       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_mm_node *stolen;
	int ret;
+2 −1
Original line number Diff line number Diff line
@@ -21,7 +21,8 @@ int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv,
					 u64 end);
void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
				 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 *
i915_gem_object_create_stolen(struct drm_i915_private *dev_priv,
			      resource_size_t size);
+7 −0
Original line number Diff line number Diff line
@@ -514,6 +514,13 @@ struct intel_l3_parity {
};

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 */
	struct drm_mm stolen;
	/** Protects the usage of the GTT stolen memory allocator. This is
+1 −1
Original line number Diff line number Diff line
@@ -908,7 +908,7 @@ static const struct intel_device_info rkl_info = {
};

#define DGFX_FEATURES \
	.memory_regions = REGION_SMEM | REGION_LMEM, \
	.memory_regions = REGION_SMEM | REGION_LMEM | REGION_STOLEN_LMEM, \
	.has_master_unit_irq = 1, \
	.has_llc = 0, \
	.has_snoop = 1, \
+1 −0
Original line number Diff line number Diff line
@@ -12194,6 +12194,7 @@ enum skl_power_gate {
#define GEN12_GLOBAL_MOCS(i)	_MMIO(0x4000 + (i) * 4) /* Global MOCS regs */

#define GEN12_GSMBASE			_MMIO(0x108100)
#define GEN12_DSMBASE			_MMIO(0x1080C0)

/* gamt regs */
#define GEN8_L3_LRA_1_GPGPU _MMIO(0x4dd4)
Loading