[PATCH 2/2] drm/vram-helper: Alternate between bottom-up and top-down placement

Thomas Zimmermann tzimmermann at suse.de
Wed Apr 22 14:40:55 UTC 2020


With limited VRAM available, fragmentation can lead to OOM errors.
Alternating between bottom-up and top-down placement keeps BOs near the
ends of the VRAM and the available pages consecutively near the middle.

A real-world example with 16 MiB of VRAM is shown below.

  > cat /sys/kernel/debug/dri/0/vram-mm
  0x0000000000000000-0x000000000000057f: 1407: free
  0x000000000000057f-0x0000000000000b5b: 1500: used
  0x0000000000000b5b-0x0000000000000ff0: 1173: free

The first free area was the location of the fbdev framebuffer. The used
area is Weston's current framebuffer of 1500 pages. Weston now cannot
do a pageflip to another 1500 page-wide framebuffer, even though enough
pages are available. The patch resolves this problem to

  > cat /sys/kernel/debug/dri/0/vram-mm
  0x0000000000000000-0x00000000000005dc: 1500: used
  0x00000000000005dc-0x0000000000000a14: 1080: free
  0x0000000000000a14-0x0000000000000ff0: 1500: used

with both of Weston's framebuffers located near the ends of the VRAM
memory.

Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
---
 drivers/gpu/drm/drm_gem_vram_helper.c | 28 ++++++++++++++++++++++-----
 include/drm/drm_gem_vram_helper.h     | 10 ++++++----
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c
index 5d5bfb38bbed4..2d0b7474288de 100644
--- a/drivers/gpu/drm/drm_gem_vram_helper.c
+++ b/drivers/gpu/drm/drm_gem_vram_helper.c
@@ -146,15 +146,33 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
 	unsigned int i;
 	unsigned int c = 0;
 	u32 invariant_flags = pl_flag & TTM_PL_FLAG_TOPDOWN;
+	struct drm_device *dev = gbo->bo.base.dev;
+	struct drm_vram_mm *vmm = dev->vram_mm;
 
 	gbo->placement.placement = gbo->placements;
 	gbo->placement.busy_placement = gbo->placements;
 
-	if (pl_flag & TTM_PL_FLAG_VRAM)
-		gbo->placements[c++].flags = TTM_PL_FLAG_WC |
-					     TTM_PL_FLAG_UNCACHED |
-					     TTM_PL_FLAG_VRAM |
-					     invariant_flags;
+	if (pl_flag & TTM_PL_FLAG_VRAM) {
+		/*
+		 * We usually have at most 2 pinned BOs during pageflips,
+		 * plus cursor BOs. Even with a significant number of free
+		 ' pages, always placing bottom-up can lead to fragmentation
+		 * and OOM situations. So if there's no explicit request for
+		 * top-down placement, we alternatingly place BOs bottom-up
+		 * and top-down. The placement strategy should help to keep
+		 * free VRAM pages available near the middle of the VRAM.
+		 */
+		gbo->placements[c].flags = TTM_PL_FLAG_WC |
+					   TTM_PL_FLAG_UNCACHED |
+					   TTM_PL_FLAG_VRAM |
+					   invariant_flags;
+		if (!(invariant_flags & TTM_PL_FLAG_TOPDOWN)) {
+			if (vmm->place_topdown)
+				gbo->placements[c].flags |= TTM_PL_FLAG_TOPDOWN;
+			vmm->place_topdown = !vmm->place_topdown;
+		}
+		++c;
+	}
 
 	if (pl_flag & TTM_PL_FLAG_SYSTEM)
 		gbo->placements[c++].flags = TTM_PL_MASK_CACHING |
diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h
index b63bcd1b996da..04767d0ff23a6 100644
--- a/include/drm/drm_gem_vram_helper.h
+++ b/include/drm/drm_gem_vram_helper.h
@@ -165,10 +165,10 @@ void drm_gem_vram_simple_display_pipe_cleanup_fb(
 
 /**
  * struct drm_vram_mm - An instance of VRAM MM
- * @vram_base:	Base address of the managed video memory
- * @vram_size:	Size of the managed video memory in bytes
- * @bdev:	The TTM BO device.
- * @funcs:	TTM BO functions
+ * @vram_base:		Base address of the managed video memory
+ * @vram_size:		Size of the managed video memory in bytes
+ * @bdev:		The TTM BO device
+ * @place_topdown:	Flags the next BO to be placed at the VRAM's high end
  *
  * The fields &struct drm_vram_mm.vram_base and
  * &struct drm_vram_mm.vrm_size are managed by VRAM MM, but are
@@ -180,6 +180,8 @@ struct drm_vram_mm {
 	size_t vram_size;
 
 	struct ttm_bo_device bdev;
+
+	bool place_topdown;
 };
 
 /**
-- 
2.26.0



More information about the dri-devel mailing list