Commit a9da512b authored by Paulo Zanoni's avatar Paulo Zanoni Committed by Daniel Vetter

drm/i915: avoid the last 8mb of stolen on BDW/SKL

The FBC hardware for these platforms doesn't have access to the
bios_reserved range, so it always assumes the maximum (8mb) is used.
So avoid this range while allocating.

This solves a bunch of FIFO underruns that happen if you end up
putting the CFB in that memory range. On my machine, with 32mb of
stolen, I need a 2560x1440 mode for that.

Testcase: igt/kms_frontbuffer_tracking/fbc-* (given the right setup)
Signed-off-by: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent adf70c65
...@@ -3175,6 +3175,10 @@ static inline void i915_gem_chipset_flush(struct drm_device *dev) ...@@ -3175,6 +3175,10 @@ static inline void i915_gem_chipset_flush(struct drm_device *dev)
int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
struct drm_mm_node *node, u64 size, struct drm_mm_node *node, u64 size,
unsigned alignment); unsigned alignment);
int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv,
struct drm_mm_node *node, u64 size,
unsigned alignment, u64 start,
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);
int i915_gem_init_stolen(struct drm_device *dev); int i915_gem_init_stolen(struct drm_device *dev);
......
...@@ -341,6 +341,7 @@ struct i915_gtt { ...@@ -341,6 +341,7 @@ struct i915_gtt {
struct i915_address_space base; struct i915_address_space base;
size_t stolen_size; /* Total size of stolen memory */ size_t stolen_size; /* Total size of stolen memory */
size_t stolen_usable_size; /* Total size minus BIOS reserved */
u64 mappable_end; /* End offset that we can CPU map */ u64 mappable_end; /* End offset that we can CPU map */
struct io_mapping *mappable; /* Mapping to our CPU mappable region */ struct io_mapping *mappable; /* Mapping to our CPU mappable region */
phys_addr_t mappable_base; /* PA of our GMADR */ phys_addr_t mappable_base; /* PA of our GMADR */
......
...@@ -42,9 +42,9 @@ ...@@ -42,9 +42,9 @@
* for is a boon. * for is a boon.
*/ */
int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv,
struct drm_mm_node *node, u64 size, struct drm_mm_node *node, u64 size,
unsigned alignment) unsigned alignment, u64 start, u64 end)
{ {
int ret; int ret;
...@@ -52,13 +52,23 @@ int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, ...@@ -52,13 +52,23 @@ int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
return -ENODEV; return -ENODEV;
mutex_lock(&dev_priv->mm.stolen_lock); mutex_lock(&dev_priv->mm.stolen_lock);
ret = drm_mm_insert_node(&dev_priv->mm.stolen, node, size, alignment, ret = drm_mm_insert_node_in_range(&dev_priv->mm.stolen, node, size,
DRM_MM_SEARCH_DEFAULT); alignment, start, end,
DRM_MM_SEARCH_DEFAULT);
mutex_unlock(&dev_priv->mm.stolen_lock); mutex_unlock(&dev_priv->mm.stolen_lock);
return ret; return ret;
} }
int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
struct drm_mm_node *node, u64 size,
unsigned alignment)
{
return i915_gem_stolen_insert_node_in_range(dev_priv, node, size,
alignment, 0,
dev_priv->gtt.stolen_usable_size);
}
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)
{ {
...@@ -355,9 +365,11 @@ int i915_gem_init_stolen(struct drm_device *dev) ...@@ -355,9 +365,11 @@ int i915_gem_init_stolen(struct drm_device *dev)
dev_priv->gtt.stolen_size >> 10, dev_priv->gtt.stolen_size >> 10,
(dev_priv->gtt.stolen_size - reserved_total) >> 10); (dev_priv->gtt.stolen_size - reserved_total) >> 10);
dev_priv->gtt.stolen_usable_size = dev_priv->gtt.stolen_size -
reserved_total;
/* Basic memrange allocator for stolen space */ /* Basic memrange allocator for stolen space */
drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size - drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_usable_size);
reserved_total);
return 0; return 0;
} }
......
...@@ -551,6 +551,16 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, ...@@ -551,6 +551,16 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
{ {
int compression_threshold = 1; int compression_threshold = 1;
int ret; int ret;
u64 end;
/* The FBC hardware for BDW/SKL doesn't have access to the stolen
* reserved range size, so it always assumes the maximum (8mb) is used.
* If we enable FBC using a CFB on that memory range we'll get FIFO
* underruns, even if that range is not reserved by the BIOS. */
if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024;
else
end = dev_priv->gtt.stolen_usable_size;
/* HACK: This code depends on what we will do in *_enable_fbc. If that /* HACK: This code depends on what we will do in *_enable_fbc. If that
* code changes, this code needs to change as well. * code changes, this code needs to change as well.
...@@ -560,7 +570,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, ...@@ -560,7 +570,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
*/ */
/* Try to over-allocate to reduce reallocations and fragmentation. */ /* Try to over-allocate to reduce reallocations and fragmentation. */
ret = i915_gem_stolen_insert_node(dev_priv, node, size <<= 1, 4096); ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size <<= 1,
4096, 0, end);
if (ret == 0) if (ret == 0)
return compression_threshold; return compression_threshold;
...@@ -570,7 +581,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, ...@@ -570,7 +581,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
(fb_cpp == 2 && compression_threshold == 2)) (fb_cpp == 2 && compression_threshold == 2))
return 0; return 0;
ret = i915_gem_stolen_insert_node(dev_priv, node, size >>= 1, 4096); ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size >>= 1,
4096, 0, end);
if (ret && INTEL_INFO(dev_priv)->gen <= 4) { if (ret && INTEL_INFO(dev_priv)->gen <= 4) {
return 0; return 0;
} else if (ret) { } else if (ret) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment