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: Paulo Zanoni <paulo.r.zan...@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h        |  4 ++++
 drivers/gpu/drm/i915/i915_gem_gtt.h    |  1 +
 drivers/gpu/drm/i915/i915_gem_stolen.c | 26 +++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_fbc.c       | 16 ++++++++++++++--
 4 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8cf2969..1f02a5a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3173,6 +3173,10 @@ static inline void i915_gem_chipset_flush(struct 
drm_device *dev)
 int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
                                struct drm_mm_node *node, u64 size,
                                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,
                                 struct drm_mm_node *node);
 int i915_gem_init_stolen(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h 
b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 8275007..96ebb98 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -341,6 +341,7 @@ struct i915_gtt {
        struct i915_address_space base;
 
        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 */
        struct io_mapping *mappable;    /* Mapping to our CPU mappable region */
        phys_addr_t mappable_base;      /* PA of our GMADR */
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c 
b/drivers/gpu/drm/i915/i915_gem_stolen.c
index bf26ecc..081ef6d 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -42,9 +42,9 @@
  * for is a boon.
  */
 
-int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
-                               struct drm_mm_node *node, u64 size,
-                               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)
 {
        int ret;
 
@@ -52,13 +52,23 @@ int i915_gem_stolen_insert_node(struct drm_i915_private 
*dev_priv,
                return -ENODEV;
 
        mutex_lock(&dev_priv->mm.stolen_lock);
-       ret = drm_mm_insert_node(&dev_priv->mm.stolen, node, size, alignment,
-                                DRM_MM_SEARCH_DEFAULT);
+       ret = drm_mm_insert_node_in_range(&dev_priv->mm.stolen, node, size,
+                                         alignment, start, end,
+                                         DRM_MM_SEARCH_DEFAULT);
        mutex_unlock(&dev_priv->mm.stolen_lock);
 
        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,
                                 struct drm_mm_node *node)
 {
@@ -355,9 +365,11 @@ int i915_gem_init_stolen(struct drm_device *dev)
                      dev_priv->gtt.stolen_size >> 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 */
-       drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size -
-                   reserved_total);
+       drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_usable_size);
 
        return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index db38091..6f3c2ea 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -551,6 +551,16 @@ static int find_compression_threshold(struct 
drm_i915_private *dev_priv,
 {
        int compression_threshold = 1;
        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
         * code changes, this code needs to change as well.
@@ -560,7 +570,8 @@ static int find_compression_threshold(struct 
drm_i915_private *dev_priv,
         */
 
        /* 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)
                return compression_threshold;
 
@@ -570,7 +581,8 @@ again:
            (fb_cpp == 2 && compression_threshold == 2))
                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) {
                return 0;
        } else if (ret) {
-- 
2.5.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to