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@xxxxxxx> --- 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel