This is one part in a few fixes needed to make FBC work with limited
stolen memory and large resolution displays. It is not the full
solution, but one (easy) step.

The patch is straight-forward, it attempts to check there will be room
for FBC before trying to "reclaim"

This modifies behavior originally introduced:
commit 0ffb0ff283cca16f72caf29c44496d83b0c291fb
Author: Chris Wilson <ch...@chris-wilson.co.uk>
Date:   Thu Nov 15 11:32:27 2012 +0000

    drm/i915: Allocate fbcon from stolen memory

Cc: Chris Wilson <ch...@chris-wilson.co.uk>
Cc: Jesse Barnes <jbar...@virtuousgeek.org>
Signed-off-by: Ben Widawsky <b...@bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_fbdev.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbdev.c 
b/drivers/gpu/drm/i915/intel_fbdev.c
index 27975c3..ca83af8 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -57,6 +57,36 @@ static struct fb_ops intelfb_ops = {
        .fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
+static bool intelfb_use_stolen(struct drm_device *dev, struct drm_mm *mm,
+                              int size)
+{
+       struct drm_mm_node *entry;
+       unsigned long adj_start;
+       unsigned long adj_end;
+
+       if (!drm_mm_initialized(mm))
+               return false;
+
+       if (!HAS_FBC(dev))
+               return true;
+
+       /* It is more desirable to use FBC (if enabled) than to allocate the
+        * framebuffer from stolen. We can cheat this by rounding up the size by
+        * 2 (and hope to get lucky with alignment). The other options are more
+        * invasive, and arguably not any more effective.
+        */
+       size *= 2;
+       __drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
+                              DRM_MM_SEARCH_DEFAULT) {
+               if (adj_end - adj_start < size)
+                       continue;
+
+               if (adj_end >= adj_start + size)
+                       return true;
+       }
+
+       return false;
+}
 static int intelfb_alloc(struct drm_fb_helper *helper,
                         struct drm_fb_helper_surface_size *sizes)
 {
@@ -64,8 +94,9 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
                container_of(helper, struct intel_fbdev, helper);
        struct drm_framebuffer *fb;
        struct drm_device *dev = helper->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_mode_fb_cmd2 mode_cmd = {};
-       struct drm_i915_gem_object *obj;
+       struct drm_i915_gem_object *obj = NULL;
        int size, ret;
 
        /* we don't do packed 24bpp */
@@ -82,7 +113,9 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
 
        size = mode_cmd.pitches[0] * mode_cmd.height;
        size = ALIGN(size, PAGE_SIZE);
-       obj = i915_gem_object_create_stolen(dev, size);
+
+       if (intelfb_use_stolen(dev, &dev_priv->mm.stolen, size))
+               obj = i915_gem_object_create_stolen(dev, size);
        if (obj == NULL)
                obj = i915_gem_alloc_object(dev, size);
        if (!obj) {
-- 
2.0.0

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

Reply via email to