[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