forked from Minki/linux
drm/i915/lmem: add the fake lmem region
Intended for upstream testing so that we can still exercise the LMEM plumbing and !i915_ggtt_has_aperture paths. Smoke tested on Skull Canyon device. This works by allocating an intel_memory_region for a reserved portion of system memory, which we treat like LMEM. For the LMEMBAR we steal the aperture and 1:1 it map to the stolen region. To enable simply set the i915 modparam fake_lmem_start= on the kernel cmdline with the start of reserved region(see memmap=). The size of the region we can use is determined by the size of the mappable aperture, so the size of reserved region should be >= mappable_end. For now we only enable for the selftests. Depends on CONFIG_DRM_I915_UNSTABLE being enabled. eg. memmap=2G$16G i915.fake_lmem_start=0x400000000 v2: make fake_lmem_start an i915 modparam 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> Cc: Arkadiusz Hiler <arkadiusz.hiler@intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> 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/20191030173320.8850-1-matthew.auld@intel.com
This commit is contained in:
parent
4974826482
commit
1629224324
@ -19,3 +19,11 @@ config DRM_I915_UNSTABLE
|
||||
Recommended for driver developers _only_.
|
||||
|
||||
If in the slightest bit of doubt, say "N".
|
||||
|
||||
config DRM_I915_UNSTABLE_FAKE_LMEM
|
||||
bool "Enable the experimental fake lmem"
|
||||
depends on DRM_I915_UNSTABLE
|
||||
default n
|
||||
help
|
||||
Convert some system memory into a fake local memory region for
|
||||
testing.
|
||||
|
@ -24,6 +24,7 @@ i915_gem_object_lmem_io_map_page(struct drm_i915_gem_object *obj,
|
||||
resource_size_t offset;
|
||||
|
||||
offset = i915_gem_object_get_dma_address(obj, n);
|
||||
offset -= obj->mm.region->region.start;
|
||||
|
||||
return io_mapping_map_wc(&obj->mm.region->iomap, offset, PAGE_SIZE);
|
||||
}
|
||||
@ -35,6 +36,7 @@ i915_gem_object_lmem_io_map_page_atomic(struct drm_i915_gem_object *obj,
|
||||
resource_size_t offset;
|
||||
|
||||
offset = i915_gem_object_get_dma_address(obj, n);
|
||||
offset -= obj->mm.region->region.start;
|
||||
|
||||
return io_mapping_map_atomic_wc(&obj->mm.region->iomap, offset);
|
||||
}
|
||||
@ -49,6 +51,7 @@ i915_gem_object_lmem_io_map(struct drm_i915_gem_object *obj,
|
||||
GEM_BUG_ON(!i915_gem_object_is_contiguous(obj));
|
||||
|
||||
offset = i915_gem_object_get_dma_address(obj, n);
|
||||
offset -= obj->mm.region->region.start;
|
||||
|
||||
return io_mapping_map_wc(&obj->mm.region->iomap, offset, size);
|
||||
}
|
||||
|
@ -1483,6 +1483,21 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (!i915_modparams.nuclear_pageflip && match_info->gen < 5)
|
||||
dev_priv->drm.driver_features &= ~DRIVER_ATOMIC;
|
||||
|
||||
/*
|
||||
* Check if we support fake LMEM -- for now we only unleash this for
|
||||
* the live selftests(test-and-exit).
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_DRM_I915_UNSTABLE_FAKE_LMEM)) {
|
||||
if (INTEL_GEN(dev_priv) >= 9 && i915_selftest.live < 0 &&
|
||||
i915_modparams.fake_lmem_start) {
|
||||
mkwrite_device_info(dev_priv)->memory_regions =
|
||||
REGION_SMEM | REGION_LMEM | REGION_STOLEN;
|
||||
mkwrite_device_info(dev_priv)->is_dgfx = true;
|
||||
GEM_BUG_ON(!HAS_LMEM(dev_priv));
|
||||
GEM_BUG_ON(!IS_DGFX(dev_priv));
|
||||
}
|
||||
}
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
goto out_fini;
|
||||
|
@ -179,6 +179,11 @@ i915_param_named(enable_gvt, bool, 0400,
|
||||
"Enable support for Intel GVT-g graphics virtualization host support(default:false)");
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_UNSTABLE_FAKE_LMEM)
|
||||
i915_param_named_unsafe(fake_lmem_start, ulong, 0600,
|
||||
"Fake LMEM start offset (default: 0)");
|
||||
#endif
|
||||
|
||||
static __always_inline void _print_param(struct drm_printer *p,
|
||||
const char *name,
|
||||
const char *type,
|
||||
@ -190,6 +195,8 @@ static __always_inline void _print_param(struct drm_printer *p,
|
||||
drm_printf(p, "i915.%s=%d\n", name, *(const int *)x);
|
||||
else if (!__builtin_strcmp(type, "unsigned int"))
|
||||
drm_printf(p, "i915.%s=%u\n", name, *(const unsigned int *)x);
|
||||
else if (!__builtin_strcmp(type, "unsigned long"))
|
||||
drm_printf(p, "i915.%s=%lu\n", name, *(const unsigned long *)x);
|
||||
else if (!__builtin_strcmp(type, "char *"))
|
||||
drm_printf(p, "i915.%s=%s\n", name, *(const char **)x);
|
||||
else
|
||||
|
@ -66,6 +66,7 @@ struct drm_printer;
|
||||
param(int, fastboot, -1) \
|
||||
param(int, enable_dpcd_backlight, 0) \
|
||||
param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE) \
|
||||
param(unsigned long, fake_lmem_start, 0) \
|
||||
/* leave bools at the end to not create holes */ \
|
||||
param(bool, alpha_support, IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT)) \
|
||||
param(bool, enable_hangcheck, true) \
|
||||
|
@ -228,6 +228,9 @@ int intel_memory_regions_hw_probe(struct drm_i915_private *i915)
|
||||
case INTEL_MEMORY_STOLEN:
|
||||
mem = i915_gem_stolen_setup(i915);
|
||||
break;
|
||||
case INTEL_MEMORY_LOCAL:
|
||||
mem = intel_setup_fake_lmem(i915);
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_ERR(mem)) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/io-mapping.h>
|
||||
#include <drm/drm_mm.h>
|
||||
|
||||
#include "i915_buddy.h"
|
||||
|
||||
@ -71,6 +72,9 @@ struct intel_memory_region {
|
||||
struct io_mapping iomap;
|
||||
struct resource region;
|
||||
|
||||
/* For fake LMEM */
|
||||
struct drm_mm_node fake_mappable;
|
||||
|
||||
struct i915_buddy_mm mm;
|
||||
struct mutex mm_lock;
|
||||
|
||||
@ -83,6 +87,8 @@ struct intel_memory_region {
|
||||
unsigned int instance;
|
||||
unsigned int id;
|
||||
|
||||
dma_addr_t remap_addr;
|
||||
|
||||
struct {
|
||||
struct mutex lock; /* Protects access to objects */
|
||||
struct list_head list;
|
||||
|
@ -9,9 +9,62 @@
|
||||
#include "gem/i915_gem_region.h"
|
||||
#include "intel_region_lmem.h"
|
||||
|
||||
static int init_fake_lmem_bar(struct intel_memory_region *mem)
|
||||
{
|
||||
struct drm_i915_private *i915 = mem->i915;
|
||||
struct i915_ggtt *ggtt = &i915->ggtt;
|
||||
unsigned long n;
|
||||
int ret;
|
||||
|
||||
/* We want to 1:1 map the mappable aperture to our reserved region */
|
||||
|
||||
mem->fake_mappable.start = 0;
|
||||
mem->fake_mappable.size = resource_size(&mem->region);
|
||||
mem->fake_mappable.color = I915_COLOR_UNEVICTABLE;
|
||||
|
||||
ret = drm_mm_reserve_node(&ggtt->vm.mm, &mem->fake_mappable);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mem->remap_addr = dma_map_resource(&i915->drm.pdev->dev,
|
||||
mem->region.start,
|
||||
mem->fake_mappable.size,
|
||||
PCI_DMA_BIDIRECTIONAL,
|
||||
DMA_ATTR_FORCE_CONTIGUOUS);
|
||||
if (dma_mapping_error(&i915->drm.pdev->dev, mem->remap_addr)) {
|
||||
drm_mm_remove_node(&mem->fake_mappable);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (n = 0; n < mem->fake_mappable.size >> PAGE_SHIFT; ++n) {
|
||||
ggtt->vm.insert_page(&ggtt->vm,
|
||||
mem->remap_addr + (n << PAGE_SHIFT),
|
||||
n << PAGE_SHIFT,
|
||||
I915_CACHE_NONE, 0);
|
||||
}
|
||||
|
||||
mem->region = (struct resource)DEFINE_RES_MEM(mem->remap_addr,
|
||||
mem->fake_mappable.size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_fake_lmem_bar(struct intel_memory_region *mem)
|
||||
{
|
||||
if (drm_mm_node_allocated(&mem->fake_mappable))
|
||||
drm_mm_remove_node(&mem->fake_mappable);
|
||||
|
||||
dma_unmap_resource(&mem->i915->drm.pdev->dev,
|
||||
mem->remap_addr,
|
||||
mem->fake_mappable.size,
|
||||
PCI_DMA_BIDIRECTIONAL,
|
||||
DMA_ATTR_FORCE_CONTIGUOUS);
|
||||
}
|
||||
|
||||
static void
|
||||
region_lmem_release(struct intel_memory_region *mem)
|
||||
{
|
||||
release_fake_lmem_bar(mem);
|
||||
io_mapping_fini(&mem->iomap);
|
||||
intel_memory_region_release_buddy(mem);
|
||||
}
|
||||
@ -21,6 +74,11 @@ region_lmem_init(struct intel_memory_region *mem)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (i915_modparams.fake_lmem_start) {
|
||||
ret = init_fake_lmem_bar(mem);
|
||||
GEM_BUG_ON(ret);
|
||||
}
|
||||
|
||||
if (!io_mapping_init_wc(&mem->iomap,
|
||||
mem->io_start,
|
||||
resource_size(&mem->region)))
|
||||
@ -38,3 +96,37 @@ const struct intel_memory_region_ops intel_region_lmem_ops = {
|
||||
.release = region_lmem_release,
|
||||
.create_object = __i915_gem_lmem_object_create,
|
||||
};
|
||||
|
||||
struct intel_memory_region *
|
||||
intel_setup_fake_lmem(struct drm_i915_private *i915)
|
||||
{
|
||||
struct pci_dev *pdev = i915->drm.pdev;
|
||||
struct intel_memory_region *mem;
|
||||
resource_size_t mappable_end;
|
||||
resource_size_t io_start;
|
||||
resource_size_t start;
|
||||
|
||||
GEM_BUG_ON(i915_ggtt_has_aperture(&i915->ggtt));
|
||||
GEM_BUG_ON(!i915_modparams.fake_lmem_start);
|
||||
|
||||
/* Your mappable aperture belongs to me now! */
|
||||
mappable_end = pci_resource_len(pdev, 2);
|
||||
io_start = pci_resource_start(pdev, 2),
|
||||
start = i915_modparams.fake_lmem_start;
|
||||
|
||||
mem = intel_memory_region_create(i915,
|
||||
start,
|
||||
mappable_end,
|
||||
PAGE_SIZE,
|
||||
io_start,
|
||||
&intel_region_lmem_ops);
|
||||
if (!IS_ERR(mem)) {
|
||||
DRM_INFO("Intel graphics fake LMEM: %pR\n", &mem->region);
|
||||
DRM_INFO("Intel graphics fake LMEM IO start: %llx\n",
|
||||
(u64)mem->io_start);
|
||||
DRM_INFO("Intel graphics fake LMEM size: %llx\n",
|
||||
(u64)resource_size(&mem->region));
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
@ -6,6 +6,11 @@
|
||||
#ifndef __INTEL_REGION_LMEM_H
|
||||
#define __INTEL_REGION_LMEM_H
|
||||
|
||||
struct drm_i915_private;
|
||||
|
||||
extern const struct intel_memory_region_ops intel_region_lmem_ops;
|
||||
|
||||
struct intel_memory_region *
|
||||
intel_setup_fake_lmem(struct drm_i915_private *i915);
|
||||
|
||||
#endif /* !__INTEL_REGION_LMEM_H */
|
||||
|
Loading…
Reference in New Issue
Block a user